有人可以解释这个汇编语言程序来找到一个字符串的反向吗?在read()之后是否未初始化使用RAX?

问题描述 投票:0回答:1
%macro read 1
Mov ax,3
mov bx,0
mov rcx,%1
mov dx,20
Int 80h
%endmacro

%macro print 2
Mov ax,4
mov bx,1
mov rcx,%1
mov dx,%2
Int 80h
%endmacro  

 section .Data
           len : db 0
   section .bss
       Str1 resb 20
       Str2 resb 20
   section .text
     global _start: 
          read str1 ;using macro
      mov [len],al
      lea rsi,[str1]
      lea rdi,[str2]
      mov rcx,rax
      dec rcx
      Add rsi,rcx
 loop1:
       Dec rsi
       Mov al,[rsi]
       Mov [rdi],al
       Inc rdi
       loop loop1
       print str2,[len]

     Exit: 
        mov ax,1
        Mov bx,0
        int 80h


使用上面的asm代码,我可以找到字符串的反序。但是在这里,在读取了字符串寄存器之后,Al移到了[[len,但是Register Al尚未初始化,并且rcx,rax保留了哪些数据?

有人可以简单地解释上面的代码吗?
assembly x86-64 nasm
1个回答
0
投票
很显然read返回RAX的长度。对于函数来说,这是完全正常的,对于宏也是有意义的。

在这种情况下,是的,它只是int 0x80的32位read() ABI周围的一个(粗大的)包装,如手册页所述,它返回一个长度。 Linux系统调用确实以RAX返回。它也奇怪地将最大长度硬编码为20。

[ ]仅使用低32位。read()

int 0x80是RAX的低字节,此代码仅保存打印长度的低字节。 IDK为什么他们将其保存在内存中,而不是像普通人一样将其保存在内存中。尤其是当他们将整个64位长度而不是普通的What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?复制到RCX以便将32位值零扩展到RCX时。

还请注意,后面的AL(32位mov ecx, eax)是有风险的,是个坏主意;它可能会在RAX的高字节中留下垃圾,从而导致mov ax,1而不是__NR_exit


使用较小的缓冲区大小将读取错误(或在返回大于4096之前返回-ENOSYS,因此在这种情况下仅替换RAX的低16位是安全的。

除非_exit(0)返回负错误代码;那么当最后一个-EFAULT返回read而不是退出时,该程序将崩溃而不是退出。

尝试用int 0x80运行它以关闭stdin,导致从[stdin]读取-ENOSYS,然后崩溃]

而且,这是64位代码,因此使用32位./a.out <&- Linux系统调用ABI并不是一个好主意。一些Linux系统(包括WSL)没有-EBADF,并且会像int 0x80或任何其他软件中断那样出错。 CONFIG_IA32_EMULATION

© www.soinside.com 2019 - 2024. All rights reserved.