反转字符串的汇编程序在打印一个字符后终止

Assembly program to reverse a string terminates after printing one character

我正在尝试编写一个汇编程序,它接受一个长度为 5 的字符串并打印反转的字符串。我尝试通过使用 ecx = 5 的循环以相反的顺序一个一个地打印字符。要打印字符,我计算反向地址,然后使用子例程打印该字符。

但是我的代码好像有错误,它只输出了第一个字符。

例如,对于给定的输入 12345,我得到 1 作为输出,但我希望它打印 54331

segment .bss
    INPT: resb 5

segment .text
        global  asm_main
asm_main:
    mov eax, 3              ; system call no (sys_read = 3)
    mov ebx, 1              ; std_in = 1
    mov ecx, INPT           ; ptr to location to store input (INPT)
    mov edx, 5              ; no of bytes to read
    int 0x80                ; issue a system call

    mov ecx, 5
swap:
    mov edx, -8
    imul edx, ecx
    add edx, 40
    add edx, INPT           ; address of next byte to print = [INPT + 5 * 8 - ecx * 8]
    call print
    loop swap
    jmp exit
print:
    push ecx
    mov eax, 4
    mov ebx, 1
    mov ecx, edx
    mov edx, 1 
    int 0x80
    pop ecx
    ret
exit:
    mov eax, 1
    xor ebx, ebx
    int 0x80
INPT: resb 5

这保留了 5 字节。 但是计算有next comment

; address of next byte to print = [INPT + 5 * 8 - ecx * 8]

期待 qword 个元素!

即使您通过将 -8 更改为 -1 来更正上述内容,您仍然不会反转 输入! lea ecx, [INPT + ecx - 1] 可以解决问题。

另外请注意 STDIN = 0 和 sys_read returns 您应该使用的计数而不是固定数字 5。
也不要使用慢 LOOP 指令,为什么不使用 ECX 寄存器中准备好的地址调用 print
最后,您可以使用未被后续调用破坏的寄存器进行循环。这节省了推和弹出。

要反转打印,请使用:

asm_main:
  mov eax, 3              ; system call no (sys_read = 3)
  xor ebx, ebx            ; std_in = 0
  mov ecx, INPT           ; ptr to location to store input (INPT)
  mov edx, 5              ; no of bytes to read
  int 0x80                ; -> EAX

  mov edi, eax
swap:
  lea  ecx, [INPT + edi - 1]  ; address of next byte to print in reverse order
  call print
  dec  edi
  jnz  swap
  jmp  exit
print:
  mov eax, 4
  mov ebx, 1
  mov edx, 1 
  int 0x80
  ret
exit:
  mov eax, 1
  xor ebx, ebx
  int 0x80