【问题标题】:x86 ASM Linux - Creating a loopx86 ASM Linux - 创建循环
【发布时间】:2011-12-08 03:03:04
【问题描述】:

我正在使用 NASM 和 x86 Intel 汇编语法在 Linux 操作系统上开发一个程序 - 它应该很简单。

我遇到的问题是我无法为我的程序创建一个工作循环:

section .data
    hello:    db 'Loop started.', 0Ah   ;string tells the user of start
    sLength:  equ $-hello               ;length of string

    notDone:  db 'Loop not finished.', 0Ah ;string to tell user of continue
    nDLength: equ $-notDone                ;length of string

    done:     db 'The loop has finished', 0Ah ;string tells user of end
    dLength:  equ $-done                      ;length of string

section .text

    global _start:
_start:
    jmp welcome         ;jump to label "welcome"

    mov ecx, 0          ;number used for loop index
    jmp loop            ;jump to label "loop"

    jmp theend          ;jump to the last label

welcome:

    mov eax, 4
    mov ebx, 1
    mov ecx, hello
    mov edx, sLength
    int 80              ;prints out the string in "hello"

loop:
    push ecx            ;put ecx on the stack so its value isn't lost

    mov eax, 4
    mov ebx, 1
    mov ecx, notDone
    mov edx, nDLength
    int 80              ;prints out that the loop isn't finished

    pop ecx             ;restore value
    add ecx, 1          ;add one to ecx's value
    cmp ecx, 10
    jl loop             ;if the value is not ten or more, repeat

theend:

;loop for printing out the "done" string

我正在打印第一个字符串,一个“未完成”和最后一个字符串;我又错过了九个“未完成”!有谁知道为什么我失去了 ecx 寄存器的价值?

谢谢。

【问题讨论】:

标签: string assembly x86 nasm


【解决方案1】:

您正在将循环寄存器 ecx 初始值设置为“hello”的地址,而不是 0:

    jmp welcome
    (mov ecx, 0)        ;number used for loop index <- jumped over
    ...
welcome:
    ...
    mov ecx, hello <- setting
    int 80         <- ecx
    ...
loop:
    push ecx            ;put ecx on the stack so its value isn't lost

【讨论】:

  • 我不明白;我看不出我的代码和你的代码有什么不同。我想我明白你的意思,但我不明白应该如何改变。
  • 这是因为它是你的代码。您在第一个 int 80 之后使用 ecx 中的任何内容作为初始循环值,而不是 0
  • mov ecx,0 实际上从未执行过。
  • int 80int 0x50。你想要int 0x80
【解决方案2】:
_start:
    jmp welcome

这意味着JMP下面的所有代码都没有被执行,尤其是mov ecx,0(对于较短的指令应该是xor ecx,ecx

不要从跳转开始,从一些代码开始。 JMP 是一个跳转,跳转后它不会返回,它只是继续执行。

所以在跳转到 Welcome: 之后,您直接转到 Loop:,因此缺少 ecx=0 代码。

cmp ecx, 10
jl loop

ECX不为0,肯定大于10h,所以不走循环。

试试这个:

_start:
    mov eax, 4
    mov ebx, 1
    mov ecx, hello
    mov edx, sLength
    int 80              ;prints out the string in "hello"
    xor ecx,ecx         ;ecx = 0

loop:
    push ecx            ;save loop index
    mov eax, 4
    mov ebx, 1
    mov ecx, notDone
    mov edx, nDLength
    int 80              ;prints out that the loop isn't finished

    pop ecx             ;get loop index back in ECX
    add ecx, 1          ;add one to ecx's value
    cmp ecx, 10
    jl loop             ;if the value is not ten or more, repeat

theend:

【讨论】:

  • 是int 80改变了寄存器,还是int 80后ecx中"hello"的地址?
  • @Jens Björnhager:EAX 将随着返回值而改变。其他寄存器保持不变。 (当然 EIP 除外)堆栈没有改变。也许除了#4 之外的其他功能,一些寄存器可能会在调用后发生变化。下面的链接很好地解释了如何在 linux 上使用 int80 进行系统调用:asm.sourceforge.net/intro/hello.html
  • 在我的程序流程中出现了一些可悲的心理错误。非常感谢。
  • int 80int 0x50。你想要int 0x80
猜你喜欢
  • 2018-09-30
  • 2018-09-02
  • 2011-12-30
  • 1970-01-01
  • 2019-09-19
  • 2021-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多