我是汇编的新手,我不知道如何将64位函数转换为32位,将16位转换为8位
以下功能的目的是在其中打印数字并返回数字。
64位:
global print_uint64
section .text
print_uint64:
mov rax,rdi
mov rdi,10
mov rsi,rsp
while:
xor rdx ,rdx
div rdi
add rdx ,48
dec rsi
mov [rsi],dl
cmp rax ,0
jne while
mov rax,1
mov rdi,1
lea rdx,[rsp]
sub rdx,rsi
syscall
lea rax,[rsp]
sub rax,rsi
ret
this works fine
32位:
global print_uint32
section .text
print_uint32:
mov eax,edi
mov edi,10
mov rsi,rsp
while:
xor edx ,edx
div edi
add edx ,48
dec rsi
mov [rsi],dl
cmp eax ,0
jne while
mov eax,1
mov edi,1
lea edx,[rsp]
sub edx,esi
syscall
lea eax,[rsp]
sub eax,esi
ret
这很好用
16位:
global print_uint16
section .text
print_uint16:
mov ax,di
mov di,10
mov rsi,rsp
while:
xor dx ,dx
div di
add dx ,48
dec rsi
mov [rsi],dl
cmp ax ,0
jne while
mov ax,1
mov di,1
lea dx,[rsp]
sub dx,si
syscall
lea ax,[rsp]
sub ax,si
ret
但是这不起作用
我研究了有关此问题的堆栈溢出问题,我理解的是我无法将rsp更改为esp,因为esp将高32位设置为零,因此当我们在该访问中使用[]时,未分配给该程序的内存因此会引发段错误。
我的问题是:
1]将64位转换为32位到16位转换为8位的基本规则是什么。
基本规则是,无论数据宽度如何,指针仍然是64位。就像在C中一样,sizeof(int*)
和sizeof(char*)
相同(在正常系统上)。
这就是为什么所有版本都必须使用dec rsi
和mov [rsi],dl
的原因:RSP拥有64位指针。将其截断为32位将不会产生有效的指针。
此外,系统调用号和fd
的大小仍然相同; mov ax,1
和mov di,1
在寄存器的高字节中留下垃圾。使用strace ./my_program
解码您实际传递给syscall
的内容。
窄版本可以将其输入零扩展到32位,然后跳转到32位版本。
但是除此之外,基本规则是尽可能使用32位操作数大小;这是x86-64(The advantages of using 32bit registers/instructions in x86-64)的自然大小。例如xor edx,edx
总是RDX / EDX / DX为零。
写一个32位寄存器零扩展到64位,不像8/16只是合并成旧值。Why do x86-64 instructions on 32-bit registers zero the upper part of the full 64-bit register?使用16位mov reg,imm16
并留下大量垃圾是大概您的系统调用无法起作用的原因。Why doesn't GCC use partial registers?
[值得注意的是,lea dx,[rsp]
/ sub dx,si
可能在RDX的高位,即write
系统调用的arg中留下垃圾。
这是一个指针减法,计算char
缓冲区中的元素数。为此,根据输入数字的大小选择操作数大小是没有意义的。只要确保将结果零扩展到RDX中,实际上就可以进行窄减法,因为在这种情况下,您知道位数最多为19(对于64位版本),因为那是多长时间2 ^ 64-1以10为底。
所以mov edx, esp
/ sub edx, esi
是所有版本中都应该执行的操作。由于完整的RSP和RSI都在附近,因此它们的差异很小。在减法之前截断输入而不是在截断之后截断结果不会改变结果;进位从低位传播到高位。参见Which 2's complement integer operations can be used without zeroing high bits in the inputs, if only the low part of the result is wanted?
使用LEA复制寄存器效率不高; lea dx, [rsp]
在结构上与mov dx, sp
相同,但速度较慢。