汇编中call printf参数压栈时错误理解

EAX, ECX,EDX,EBX均可以32bit,16bit,8bit访问,如下所示:

<-------------------EAX------------------------>
|<----------------------|-----------|----------->|
             |<---------AX--------->|
             |<---AH--->|<---AL--->|

  测试代码如下:

 1 .section .data
 2 output:
 3     .asciz "Value is:%x
"
 4 val:
 5     .int 0
 6     
 7 .section .text
 8 .globl main
 9 main:
10     nop
11     movl $0x12345678, %eax
12     movl $0, %ecx
13     movw %ax, %cx
14     pushw %cx
15     pushl $output
16     call printf
17     addl $6, %esp
18     
19     movl $1, %eax
20     movl $0, %ebx
21     int $0x80

  我的电脑是小端格式(MSB存于高位),所以预期的输出结果是:0x5678,但是我编译执行后结果是:0x2dec5678,前面多出了2个字节,但是明明我压栈的时候使用的pushw,原来是printf获取参数时使用的是4字节长度,所以虽然我压入的只有2个字节,但是它访问时以4字节访问。

  将代码修改:

 1 .section .data
 2 output:
 3     .asciz "Value is:%x
"
 4 val:
 5     .int 0
 6     
 7 .section .text
 8 .globl main
 9 main:
10     nop
11     movl $0x12345678, %eax
12     movl %eax, %ecx
13     pushl %ecx
14     pushl $output
15     call printf
16     addl $8, %esp
17 
18     movl $0, %ecx
19     movw %ax, %cx
20     pushl %ecx
21     pushl $output
22     call printf
23     addl $8, %esp
24     
25     movl $1, %eax
26     movl $0, %ebx
27     int $0x80

  预期输出:

    Value is:12345678
    Value is:5678

  结果输出:

    Value is:12345678
    Value is:12

   起先还以为是将0x12345678的最高字节0x12传送到cx里面了,觉得相当怪异,明明使用的是movw,要错也是0x1234,分析了下,原来又是printf作怪,函数调用后,其返回值一般是存储在eax里面来传递的,而第一个printf的输出:Value is:12345678恰好有0x12,18个字符(含' '),所以代码执行完15行的call后,eax的值已被printf的返回值修改,而不是我预期的0x12345678。所以汇编里面调用库函数时,要特别注意某些特殊寄存器的特殊用途,特别是这些库是由其他高级语言通过编译工具生成的时候。

原文地址:https://www.cnblogs.com/thammer/p/4311621.html