下面是一个x86组装程序,由NASM在64位CentOS下在远程终端上组装,与C程序一起使用时工作非常好。
section .data
section .text
global strlen
strlen:
push ebp
mov ebp, esp ; obtain the address of the
mov eax, DWORD [ebp+8] ; address of string to eax
xor ecx, ecx ; initialize counter to zero
count_loop:
mov bl, [eax] ; obtain the address of the 1st character
cmp bl, 0 ; check the null value
je length_exit ; exit if the null-character is reached
inc ecx ; increment counter
inc eax ; increment the address
jmp count_loop ; start the loop again
length_exit:
mov eax, ecx ; return ecx
pop ebp ;
ret首先,它是32位还是64位程序?如果它是一个32位程序,为什么它在函数的名称中没有下划线字符(_)?
我知道下面的代码部分正在创建堆栈框架:
push ebp
mov ebp, esp ; obtain the address of the
mov eax, DWORD [ebp+8] ; address of string to eax但是,为什么我们需要拯救ebp呢?为什么我们不能只写以下几句呢?
move eax, DWORD [esp+8]我们为什么要在这里做模特儿?
我还需要这个程序的内存布局来理解堆栈机制。我在互联网上发现了很多图片,但我不确定哪一张是代表这个程序的合适图片。
发布于 2019-04-04 22:04:43
如果它是一个32位程序,为什么它在函数的名称中没有下划线字符(
_)?
因为这不是Windows。
Linux/ELF系统在任何模式下都不使用领先的_,而不管其体系结构如何。
为什么我们不能只写以下内容呢?:
move eax, DWORD [esp+8]
你可以。(如果拼写正确,则为mov )。事实上,编译器在启用优化时默认使用-fomit-frame-pointer,因此他们只在带有C99可变长度数组或alloca的函数中使用EBP作为框架指针。
32位和64位模式允许ESP成为寻址模式的基本地址,而在16位模式下,[sp+2]是不可编码的。
但是请记住,如果您没有按ebp,ESP仍然指向返回地址,所以第一个arg将位于[esp+4]。
我们为什么要在这里做模特儿?
您不需要。寄存器操作数意味着操作数大小.
(这不是真正的类型转换,只是操作数大小的说明符。)它不会对您进行浮点数转换;为此您必须使用cvtss2si eax, [esp+4]。)
您只需要为mem提供一个操作数大小的说明符,即像cmp dword [esp+4], 0这样的即时指令,它在字节/word/dword操作数大小之间是不明确的。或者用于movzx eax, byte [esp+4]这样的指令,其中寄存器操作数并不意味着内存操作数的大小。
发布于 2019-04-04 22:05:12
其原因源于指令的编码方案。
“英特尔手册”第2.1.5节的表2.2显示了可能的组合。
它表明,ESP寄存器的(可能的)编码用于指示SIB字节(指令扩展字节)如下:
--命名意味着SIB遵循ModR/M字节。
因此,从本质上说,ESP寄存器的编码被重用,用于编码额外的指令字节,即SIB字节。
在SIB字节中,[ESP]的指令编码也是一个例外。参见表2.3。
https://stackoverflow.com/questions/55524895
复制相似问题