Assembly 两个数字相加在汇编中是如何工作的
我不熟悉汇编语言,我试图理解一个简单的程序,它将添加两个NUNBER并显示结果Assembly 两个数字相加在汇编中是如何工作的,assembly,x86,Assembly,X86,我不熟悉汇编语言,我试图理解一个简单的程序,它将添加两个NUNBER并显示结果 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
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
现在产量是45100
添加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
我想知道的是执行“callprintf”时会发生什么情况
“添加esp,8”的姿势是什么 printf库可能以多种方式实现,因此断言
所有printf
例程将以此printf
动作的方式执行是危险的
序列
推送eax//将100推送至堆栈
将ebx//推45到堆栈上
push message1//将消息“value=%d”的地址推送到堆栈上
调用printf//将返回地址推送到堆栈
使用进入printf
例程,从底部读取堆栈
回信地址
指向消息的指针
一些参数值
所以,PRINTF
最有可能
POP
返回地址并保存
POP
指向消息的指针
MOV
e将堆栈指针
移到寄存器或保存它
然后它就可以开始它的任务了——使用指向消息的指针,写出每个字符,直到它遇到一个像%d
这样的键串,上面写着“将某物打印为十进制”。因此,它POP
s堆栈中的下一个值(45,在ebx
中推入),将其格式化为十进制并打印,然后继续使用printf
字符串
另一个%d
-从eax
推送的100,然后继续-直到找到表示字符串结束的0
字节
现在要返回的所有printf
需要做的就是将堆栈指针
从其存储的位置还原,并返回到返回地址-无论其存储在何处
当它返回时,堆栈将恢复到调用printf
时的状态-当时,EBX
和EAX
已经PUSH
ed。每个是4个字节,因此,堆栈指针
需要调整8个字节,以删除这两条推送
指令存储的数据
那么-为什么要这样做-为什么不简单地使用allwPRINTF
来调整堆栈-它可以调整堆栈,因为它知道它已删除8个字节用于显示(2*%d)
实际上,它可以-但假设消息只包含一个%d-或3-或消耗8字节以外的内容?返回时,堆栈指针
将包含意外值-这取决于PRINTF
如何解释字符串。如果不特别小心,很难使用汇编程序技巧,例如覆盖部分消息。正如所写的那样,printf
函数始终以可预测的方式运行,在弹出消息地址后返回,而不考虑任何其他因素。由程序员来正确处理堆栈内容。调用printf将是您自己的汇编语言独有的功能,可以弹出或使用推送到堆栈上的打印数据。add esp 8位使堆栈指针跳转到ret命令的正确位置。这将弹出堆栈并直接跳到该位置。如果是错误的值,程序将返回错误的内存位置并崩溃。(您可以尝试删除add esp,8,看看会发生什么)有3个参数,应该是add esp,12
。我喜欢将其写成添加esp,4*3,这样可以很容易地更改参数的数量…我想你是对的,Frank。对于3个参数,它应该是添加esp 12,但在上面的例子中,“call printf”也将一个参数推到堆栈中,从而添加esp,16。想听听你那边的一两句话。感谢Peter的友好回复,有一件事我想知道push message1会将message1在Memory中的地址推送到存储字符串常量“value=%d”的位置,这样说安全吗?printf和printf的区别推送的值是Message1的第一个字节的地址,即指向Message1的指针。就我而言,printf
和printf
之间没有区别。大多数汇编器都会允许这两种情况——我倾向于用大写字母强调。但最好保持一致性,尤其是在学习环境中。Peter再次提出一个小问题,我们的PRINTF将弹出堆栈内容,并将SP移动到正确的位置,在其上方,我们显式地称之为add esp,12,ESP tp的位置不对吗?printf的返回地址将存储在哪里?嗯-再次查看您的代码,在几个小时的睡眠后,我建议堆栈指针不会被调用printf
更改。在原始列表中将8
添加到ESP
时,应将12
-4分别添加到EBX
和EAX
上,4分别添加到指向消息1的指针上。这会更有意义。负责在堆栈上放置
数据的代码部分也负责删除
数据。PRINTF
例程只需设置一个指向堆栈上数据的指针,返回地址为PRINTF
4字节时,堆栈上的数据将为ESP+4:最后一个项再次按下hanks-Peter,因此可以安全地假设Call PRINTF将使用其他寄存器来存储堆栈地址,而不是ESP,以及为什么我们不向ESP添加16,因为返回地址也被推送到堆栈上。