关键字:movsx movzx movq
本文参考如下:Richard Blum《Professional Assembly Language》
1、基本数字类型:
intel系列cpu支持以下数据类型:
Unsigned integers
Signed integers
Binary-coded decimal
Packed Binary-coded decimal
Single-precision floating-point
Double-precision floating-point
Double-extended floating-point
2、在奔腾以上处理器增加了增加一些高级数字类型:
64-bit packed integers
128-bit packed integers
128-bit packed single-precision floating-point
128-bit packed double-precision floating-point
gas中,整型是常用的一个数据类型,有以下基本整型:
Byte:8 bits
Word:16 bits
Doubleword :32 bits
Quadword :64 bits
不是byte的整型其数据在内存中与寄存器的字节顺序有所不同,在内存中intel系列cpu是little-endian格式进行存放,在寄存器中是采用big-endian格式进行数据存放。如图所示:
cpu隐式处理在内存中的字节顺序与寄存器的字节顺序的转换 示例:endiantest.s 1)代码
/********************************* 本程序查看内存变量与寄存器变量 用gdb的x/x x/4b这样的方式查看内存变量与寄存器 *************************************/ .section .data output: .long 0x3276 .section .text .globl _start _start: nop; movl output,%eax movl $1,%eax |
2)、编译连接调试
as -o endiantest.o endiantest.s -gstabs
ld -o endiantest.exe endiantest.o
gdb -q endiantest.exe
调试过程如下:
(gdb) x/x &output
0x402000 <output>: 0x00003276
(gdb) x/4b &output
0x402000 <output>: 0x76 0x32 0x00 0x00
从调试结果看到,低位值放到了低内存
位数 | 无符号 | 有符号 |
8 bits | 0~28-1 | -28-1~28-1 -1 |
0~255 | -128~127 | |
16 bits | 0~216-1 | -216-1~216-1 -1 |
0~65535 | -32768~32767 | |
32 bits | 0~232-1 | -232-1~232-1 -1 |
0 ~4294967295 | -2147483648~2147483647 | |
64 bits | 0~264-1 | -264-1~264-1 -1 |
有符号数扩展失真的问题,寄存器有8位、16位、32位之分,如16分的有符号数在16位寄存器中传递给32位寄存器,到了32位寄存器就其值就会发生变化。汇编语言默认的寄存器中的数为有符号数。如al中的值为:0xFF,打印出来应该是-1而不是255.
/********************************* 测试把16位值移到32位值,看其变化 *************************************/ .section .data value: .byte 0xff value2: .short 0xffbe #值为-66 .section .text .globl _start _start: nop; movw value,%bx movw value2,%cx movl $1,%eax ret |
通过gdb调试得到结果如下:
(gdb) n 13 movw value,%bx (gdb) n 14 movw value2,%cx (gdb) n 15 movl $1,%eax (gdb) info reg eax 0x76141182 1981026690 ecx 0xffbe 65470 edx 0x401000 4198400 ebx 0x7ffdbeff 2147335935 esp 0x22ff8c 0x22ff8c ebp 0x22ff94 0x22ff94 esi 0x0 0 edi 0x0 0 eip 0x40100f 0x40100f <start+15> eflags 0x246 [ PF ZF IF ] cs 0x1b 27 ss 0x23 35 ds 0x23 35 es 0x23 35 fs 0x3b 59 gs 0x0 0 (gdb) x/dh &value2 0x402001 <value2>: -66 |
ecx寄待的值是-66,但显示出了65470。这表示把16位数拓展到32位数,数据发生的失真
movsx指令用来把8位、16位进行符号扩展后把值赋值给16位、32位寄存器或内存。通过movsx能确保数据传递的正确。movsx有符号展
# movsxtest.s -an example of MOVSX instruction .section .text .globl _start _start: nop movw $-79,%cx movl $0,%ebx movw %cx,%bx movsx %cx,%eax movl $1,eax ret |
gdb调试如下:
(gdb) info reg eax 0xffffffb1 -79 ecx 0xffb1 65457 edx 0x401000 4198400 ebx 0xffb1 65457 esp 0x22ff8c 0x22ff8c ebp 0x22ff94 0x22ff94 esi 0x0 0 |
从输出看 movsx指,到高位中的用当前数的最高位进行填,如当前位为1就是1,所0xffb1(-79)从cx到eax成了(0xffffffb1)
movzx指令用来把8位、16位数扩展转换成16位、32位。movzx,数成正数了。
# movzxtest.s -an example of MOVZX instruction .section .text .globl _start _start: nop movw $-79,%cx movl $0,%ebx movw %cx,%bx movzx %cx,%eax movl $1,%eax ret |
gdb调试输出信息如下:
(gdb) info reg eax 0xffb1 65457 ecx 0xffb1 65457 edx 0x401000 4198400 ebx 0xffb1 65457 esp 0x22ff8c 0x22ff8c ebp 0x22ff94 0x22ff94 |
.globl _a .data .align 8 _a: .long -1 .long 2147483647 |
解释如下:.align 8指示其对齐地址按照8的倍数进行,8个字节用2个long类型表示,按照little-endian,第一个.long存64位整数的低位
评论