如何在Assembly中添加两个数字

时间:2013-06-06 10:56:28

标签: assembly x86

我是汇编语言的新手,并试图理解一个简单的程序,它会添加两个nunbers并显示结果。

section .data

message1 db "value=%d%d",10,0

 section .text
   global main
   extern printf
   main:
   mov eax, 55
   mov ebx, 45
   add eax,ebx
   push eax
   push ebx
   push message1
   call printf
   add esp, 8
   ret

现在输出结果是45 100

添加eax后,ebx指令结果将存储在eax寄存器中。

但现在接下来会发生什么

 push eax   // push 100 on to stack

 push ebx   // push 45 on to stack

 push message1  // push "value=%d" on to stack // I m bit doubtful here 

我想知道的是当执行“call printf”时会发生什么?

“添加esp,8”的用途是什么?

1 个答案:

答案 0 :(得分:1)

printf库可以通过多种方式实现,因此断言ALL printf例程将以THIS {{1}的方式执行会很危险行为。

序列

push eax //将100推到堆栈    push ebx // push 45 on stack    push message1 //将消息“value =%d”的地址推送到堆栈    call printf //将RETURN ADDRESS推送到堆栈

进入printf例程,从BOTTOM读取堆栈

  1. 返回地址
  2. 指向消息的指针
  3. 一些参数值
  4. 所以,printf最有可能

    1. PRINTF返回地址并保存
    2. POP指向消息的指针
    3. POP MOV到注册表或保存
    4. 然后它可以执行它的任务 - 使用指向消息的指针,将每个字符写出来,直到遇到像STACK POINTER这样的键字符串,其中“将某些内容打印为十进制”。所以%d是堆栈中的下一个值(45,在POP中推送),将其格式化为十进制并打印出来,然后继续使用ebx字符串。

      另一个printf - 从%d推送100,然后继续 - 直到找到指示字符串结尾的eax字节。

      现在需要返回的所有0都是从存储的任何地方恢复printf,并返回到返回地址 - 无论存储在何处。

      当它返回时,堆栈将恢复到调用stack pointer时的状态 - 当时printfEBXEAX编辑。每个都是4个字节,因此PUSH需要调整8个字节,以删除这两个stack pointer指令存储的数据。

      所以 - 为什么这样做 - 为什么不简单地让PUSH来调整堆栈 - 它可以,因为它知道它被移除了8个字节用于显示(2 *%d)?

      嗯,从本质上讲,它可以 - 但是假设消息只包含一个%d - 或3 - 或者消耗了8个字节以外的东西?返回时,PRINTF将包含一个意外值 - 这取决于stack-pointer如何解释字符串。非常难以拉动汇编程序技巧,例如在非常小心的情况下覆盖部分邮件。正如它所写的那样,PRINTF函数总是以可预测的方式起作用,返回弹出消息地址,而不管其他任何考虑因素。由程序员来正确处理堆栈内容。