linux - 带有 cx 寄存器的 NASM 汇编器无限循环

标签 linux assembly x86 nasm system-calls

section .data:
         msg1: db "Hello 10 times!"
         msglen1: equ $-msg1
section .text:
        global _initial:
        global _start:
        global _end:
_initial:
        mov cx,10
_start:
        dec cx
        mov ecx,msg1
        mov edx,msglen1
        mov eax,4
        int 80h
        cmp cx,0 
        jz _end
        jmp _start
_end
        mov eax,1
        int 80h

上面的代码必须生成“Hello 10 times”10 次。但它进入了无限循环,我不明白为什么? 我认为 cx 寄存器不会减少或其他什么?

最佳答案

你有很多问题。

  • Linux 程序的默认入口点是 _start。您的程序从标签 _start 而不是 initial 开始执行,因此您的循环计数器未被初始化。

  • 部分名称中没有 :global1

    的标签也没有
  • SYS_Write 系统调用缺少一个参数。 32 位系统调用是 documented in a table :

    enter image description here

    您需要将EBX 设置为文件描述符。标准输入=0,标准输出=1,标准错误=2。您想写入控制台,因此您需要在调用 Int 80h

  • 之前将 EBX 设置为 1
  • 您正在破坏 SYS_Write 系统调用的参数之一 (ECX)。 CXECX 是同一寄存器的一部分。 CXECX 的低 16 位。更改 CX 会更改 ECX。您需要为循环计数器使用其他一些寄存器。 ESIEDIEBP 当前未在您的代码中使用。将所有出现的 CX 更改为 32 位寄存器 ESI

您的代码可能如下所示:

section .data
        msg1: db "Hello 10 times!", 10
                               ; Add 10 on the end of the string for Line Feed
                               ;     so each message prints on separate line
        msglen1 equ $-msg1

section .text
        global _initial
        global _start
        global _end

_start:
        mov esi, 10            ; Initialize loop counter
_msgloop:
        dec esi                ; Decrement loop counter
        mov ebx, 1             ; File Descriptor 1 = Write to Standard Output (STDOUT)
        mov ecx, msg1          ; Address of message to print
        mov edx, msglen1       ; Length of message to print
        mov eax, 4             ; SYS_Write system call = 4
        int 80h
        cmp esi, 0             ; Has the loop counter reached 0?
        jz _end                ; If it has then we are done
        jmp _msgloop           ; otherwise go back and print message again
_end:
        mov eax,1              ; SYS_Exit system call
        int 80h

你可以这样重写你的循环:

section .data
        msg1: db "Hello 10 times!", 10
                               ; Add 10 on the end of the string for Line Feed
                               ;     so each message prints on separate line
        msglen1 equ $-msg1

section .text
        global _start

_start:
        mov esi, 10            ; Initialize loop counter

.msgloop:
        mov ebx, 1             ; File Descriptor 1 = Write to Standard Output (STDOUT)
        mov ecx, msg1          ; Address of message to print
        mov edx, msglen1       ; Length of message to print
        mov eax, 4             ; SYS_Write system call = 4
        int 80h
        dec esi                ; Decrement loop counter
        jnz .msgloop           ; If loop counter hasn't reached zero then print again

        mov eax,1              ; SYS_Exit system call
        int 80h

脚注:

  • 1您不需要将initialend 设为全局,因为您没有链接到任何其他目标文件。可以删除那些 global 行。

关于linux - 带有 cx 寄存器的 NASM 汇编器无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57377418/

相关文章:

linux - 为什么这个程序的 32 位和 64 位编译版本以这种方式填充内存?

c++ - 从我的 C/C++ 代码中获取等效的汇编代码 - x86 和 ARM

php - Laravel Forbidden 您无权访问此服务器上的/storage/

linux - 使进程保持事件状态并跟踪最新的 pid

python - 安装 Panda3d 以使用 python 运行

c - 已编译二进制文件中的预初始化函数指针?

linux - bash脚本: word occurrences in web sites

assembly - 为什么gnu链接器的 `--oformat binary'选项将 `.data'段放在0x0200000

assembly - CMP 和 2 的补码

floating-point - 浮点加法与浮点乘法的相对速度是多少