x86 NASM 程序集 - 堆栈问题

发布于 2024-12-13 08:47:33 字数 1959 浏览 2 评论 0原文

我正在开发一个程序,只需接受用户的输入两次,然后稍后将结果打印到标准输出。我遇到的问题是,当结果从输入中断(在eax中)返回时,我将其推入堆栈以供稍后使用。我对第二个用户输入再次执行此操作。

到目前为止,我的代码是:

%include "system.inc" ; used for renaming of interrupts (sys.write and sys.read)

section .data
    greet:      db 'Hello!', 0Ah, 'What is your name?', 0Ah
    greetL:     equ $-greet     ;length of string
    colorQ:     db 'What is your favorite color?', 0Ah
    colorL:     equ $-colorQ 
    suprise1:   db 'No way '
    suprise1L:  equ 7
    comma:      db ', '
    commaL:     equ $-comma
    suprise3:   db ' is my favorite color, too!', 0Ah
    suprise3L:  equ $-suprise3


section .bss

name: resb 50
color: resb 50

section .text

    global _start
_start:


greeting:
    mov eax, 4
    mov ebx, 1
    mov ecx, greet
    mov edx, greetL
    sys.write

getname:
    mov eax, 3
    mov ebx, 0
    mov ecx, name
    mov edx, 50
    sys.read

    xor ecx, ecx
    mov eax, ecx
    push ecx

askcolor:
    mov eax, 4
    mov ebx, 1
    mov ecx, colorQ
    mov edx, colorL
    sys.write

getcolor:
    mov eax, 3
    mov ebx, 0
    mov ecx, color
    mov edx, 50
    sys.read

    xor ebx, ebx
    mov ebx, eax
    push ebx


thesuprise:
    mov eax, 4
    mov ebx, 1
    mov ecx, suprise1
    mov edx, suprise1L
    sys.write

    xor ebx, ebx
    xor ecx, ecx
    xor edx, edx    
    pop ecx
    sub ecx, 1
    mov edx, ecx

    mov eax, 4
    mov ebx, 1
    mov ecx, name
    mov edx, edx
    sys.write

    mov eax, 4
    mov ebx, 1
    mov ecx, comma
    mov edx, commaL
    sys.write

    xor ebx, ebx
    xor ecx, ecx
    xor edx, edx
    pop ebx
    sub ebx, 1
    mov edx, ebx

    mov eax, 4
    mov ebx, 1
    mov ecx, color
    mov edx, edx
    sys.write

    mov eax, 4
    mov ebx, 1
    mov ecx, suprise3
    mov edx, suprise3L
    sys.write

done:

    mov eax, 1  
    mov ebx, 0  
    sys.exit

我在输出中遇到了严重的间距问题,很可能是因为我在推送/弹出它时如何处理 eax 中返回的值。有什么办法可以解决这个问题/我做错了吗?

I am working on a program to simply take in a user's input twice, and then print the result out to the standard output at a later time. The problem I am having is that, when the result is returned from the input interrupt (in eax), I push it onto the stack for use later. I do this again for the second user input.

The code I have so far is:

%include "system.inc" ; used for renaming of interrupts (sys.write and sys.read)

section .data
    greet:      db 'Hello!', 0Ah, 'What is your name?', 0Ah
    greetL:     equ $-greet     ;length of string
    colorQ:     db 'What is your favorite color?', 0Ah
    colorL:     equ $-colorQ 
    suprise1:   db 'No way '
    suprise1L:  equ 7
    comma:      db ', '
    commaL:     equ $-comma
    suprise3:   db ' is my favorite color, too!', 0Ah
    suprise3L:  equ $-suprise3


section .bss

name: resb 50
color: resb 50

section .text

    global _start
_start:


greeting:
    mov eax, 4
    mov ebx, 1
    mov ecx, greet
    mov edx, greetL
    sys.write

getname:
    mov eax, 3
    mov ebx, 0
    mov ecx, name
    mov edx, 50
    sys.read

    xor ecx, ecx
    mov eax, ecx
    push ecx

askcolor:
    mov eax, 4
    mov ebx, 1
    mov ecx, colorQ
    mov edx, colorL
    sys.write

getcolor:
    mov eax, 3
    mov ebx, 0
    mov ecx, color
    mov edx, 50
    sys.read

    xor ebx, ebx
    mov ebx, eax
    push ebx


thesuprise:
    mov eax, 4
    mov ebx, 1
    mov ecx, suprise1
    mov edx, suprise1L
    sys.write

    xor ebx, ebx
    xor ecx, ecx
    xor edx, edx    
    pop ecx
    sub ecx, 1
    mov edx, ecx

    mov eax, 4
    mov ebx, 1
    mov ecx, name
    mov edx, edx
    sys.write

    mov eax, 4
    mov ebx, 1
    mov ecx, comma
    mov edx, commaL
    sys.write

    xor ebx, ebx
    xor ecx, ecx
    xor edx, edx
    pop ebx
    sub ebx, 1
    mov edx, ebx

    mov eax, 4
    mov ebx, 1
    mov ecx, color
    mov edx, edx
    sys.write

    mov eax, 4
    mov ebx, 1
    mov ecx, suprise3
    mov edx, suprise3L
    sys.write

done:

    mov eax, 1  
    mov ebx, 0  
    sys.exit

I get severe problems with spacing in the output, most likely because of how I handle the values returned in eax when I push/pop it. Is there any way to fix this/ am I doing this wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

葵雨 2024-12-20 08:47:33
greeting:
    mov eax, 4
    mov ebx, 1
    mov ecx, greet
    mov edx, greetL
    sys.write

getname:
    mov eax, 3
    mov ebx, 0
    mov ecx, name
    mov edx, 50
    sys.read

我不知道这些 sys.writesys.read 宏将为您做什么,但它们很可能会加载 eax 在使用 int 0x80 调用系统调用之前使用正确的值,因此您可能不需要自己执行此操作。否则它们没有多大意义...

(但这不是问题;43writewrite 的正确系统调用编号。 code>read 分别在 32 位 Linux x86 上。)

实际的问题可能在这里:

    xor ecx, ecx
    mov eax, ecx
    push ecx

这看起来是错误的:您将 ecx 与其自身进行异或运算,这将其设置为零。然后,您将 ecx(现在为 0)分配给 eax(系统调用的结果),因此系统调用的结果被丢弃。然后你将ecx(仍然是0)压入堆栈。

更进一步,你有:

    xor ebx, ebx
    xor ecx, ecx
    xor edx, edx    
    pop ecx
    sub ecx, 1
    mov edx, ecx

...这也很奇怪:为什么使用 xor 指令将 ecx 和 edx 为零,当你只是要从其他地方重新加载它们,然后再执行一些说明吗?


我猜您可能只是将 mov 的操作数搞错了。而不是:

    xor ecx, ecx
    mov eax, ecx
    push ecx

...如果您说:

    xor ecx, ecx
    mov ecx, eax
    push ecx

...您至少会成功地将 eax 中的值(系统调用的返回代码)推送到堆栈上,尽管它将是简单地说:

    push eax

最后:你问“名称”问题,并且(假设上面的问题已修复)将结果长度压入堆栈。然后你问“颜色”问题,并将结果长度压入堆栈。

但是然后你使用从堆栈中弹出的第一个值打印“名称”惊喜,这是你从“颜色”问题中保存的长度。 (堆栈是后进先出的!)然后,您可以使用“名称”问题的长度来打印“颜色”惊喜。

greeting:
    mov eax, 4
    mov ebx, 1
    mov ecx, greet
    mov edx, greetL
    sys.write

getname:
    mov eax, 3
    mov ebx, 0
    mov ecx, name
    mov edx, 50
    sys.read

I don't know what these sys.write and sys.read macros are expected to do for you, but the chances are that they load eax with the correct value before invoking a syscall with int 0x80, so you probably don't need to do it yourself. There's not much point in them otherwise...

(That's not the problem though; 4 and 3 are the correct syscall numbers for write and read respectively on 32-bit Linux x86.)

The actual problem is probably here:

    xor ecx, ecx
    mov eax, ecx
    push ecx

This looks wrong: you are exclusive-ORing ecx with itself, which sets it to zero. Then you're assigning ecx (which is now 0) to eax (which is the result of the syscall), so the result of the syscall gets thrown away. Then you're pushing ecx (which is still 0) onto the stack.

Still further on, you have:

    xor ebx, ebx
    xor ecx, ecx
    xor edx, edx    
    pop ecx
    sub ecx, 1
    mov edx, ecx

...which is also odd: why zero ecx and edx with the xor instructions, when you're just going to reload them from elsewhere a couple of instructions further on?


I guess you may just have the operands of the mov the wrong way round. Instead of:

    xor ecx, ecx
    mov eax, ecx
    push ecx

...if you said:

    xor ecx, ecx
    mov ecx, eax
    push ecx

....you would at least successfully push the value that was in eax (the return code from the syscall) onto the stack, although it would be a lot simpler to just say:

    push eax

Finally: you ask the "name" question, and (assuming the above it fixed) push the resulting length on the stack. Then you ask the "color" question, and push the resulting length on the stack.

But then you print the "name" surprise, using the first value popped from the stack, which is the length you saved from the "color" question. (A stack is last-in-first-out!) Then you use print the "color" surprise using the length from the "name" question.

花想c 2024-12-20 08:47:33

感谢马特和奥特。

这是解决方案:

%include "system.inc"

section .data
    greet:      db 'Hello!', 0Ah, 'What is your name?', 0Ah
    greetL:     equ $-greet     ;length of string
    colorQ:     db 'What is your favorite color?', 0Ah
    colorL:     equ $-colorQ 
    suprise1:   db 'No way '
    suprise1L:  equ 7
    comma:      db ', '
    commaL:     equ $-comma
    suprise3:   db ' is my favorite color, too!', 0Ah
    suprise3L:  equ $-suprise3


section .bss

name: resb 50
color: resb 50

section .text

    global _start
_start:


greeting:
    mov eax, 4
    mov ebx, 1
    mov ecx, greet
    mov edx, greetL
    sys.write

getname:
    mov eax, 3
    mov ebx, 0
    mov ecx, name
    mov edx, 50
    sys.read

    sub eax, 1
    push eax

askcolor:
    mov eax, 4
    mov ebx, 1
    mov ecx, colorQ
    mov edx, colorL
    sys.write

getcolor:
    mov eax, 3
    mov ebx, 0
    mov ecx, color
    mov edx, 50
    sys.read

    sub eax, 1
    push eax


thesuprise:
    mov eax, 4
    mov ebx, 1
    mov ecx, suprise1
    mov edx, suprise1L
    sys.write

    xor eax, eax
    pop eax
    mov ecx, eax
    pop eax
    mov edx, eax
    push ecx

    mov eax, 4
    mov ebx, 1
    mov ecx, name
    ;mov edx, edx
    sys.write

    mov eax, 4
    mov ebx, 1
    mov ecx, comma
    mov edx, commaL
    sys.write

    xor eax, eax
    pop eax
    mov edx, eax

    mov eax, 4
    mov ebx, 1
    mov ecx, color
    ;mov edx, edx
    sys.write

    mov eax, 4
    mov ebx, 1
    mov ecx, suprise3
    mov edx, suprise3L
    sys.write

done:

    mov eax, 1  
    mov ebx, 0  
    sys.exit

Thanks to Matt and ott.

Here is the solution:

%include "system.inc"

section .data
    greet:      db 'Hello!', 0Ah, 'What is your name?', 0Ah
    greetL:     equ $-greet     ;length of string
    colorQ:     db 'What is your favorite color?', 0Ah
    colorL:     equ $-colorQ 
    suprise1:   db 'No way '
    suprise1L:  equ 7
    comma:      db ', '
    commaL:     equ $-comma
    suprise3:   db ' is my favorite color, too!', 0Ah
    suprise3L:  equ $-suprise3


section .bss

name: resb 50
color: resb 50

section .text

    global _start
_start:


greeting:
    mov eax, 4
    mov ebx, 1
    mov ecx, greet
    mov edx, greetL
    sys.write

getname:
    mov eax, 3
    mov ebx, 0
    mov ecx, name
    mov edx, 50
    sys.read

    sub eax, 1
    push eax

askcolor:
    mov eax, 4
    mov ebx, 1
    mov ecx, colorQ
    mov edx, colorL
    sys.write

getcolor:
    mov eax, 3
    mov ebx, 0
    mov ecx, color
    mov edx, 50
    sys.read

    sub eax, 1
    push eax


thesuprise:
    mov eax, 4
    mov ebx, 1
    mov ecx, suprise1
    mov edx, suprise1L
    sys.write

    xor eax, eax
    pop eax
    mov ecx, eax
    pop eax
    mov edx, eax
    push ecx

    mov eax, 4
    mov ebx, 1
    mov ecx, name
    ;mov edx, edx
    sys.write

    mov eax, 4
    mov ebx, 1
    mov ecx, comma
    mov edx, commaL
    sys.write

    xor eax, eax
    pop eax
    mov edx, eax

    mov eax, 4
    mov ebx, 1
    mov ecx, color
    ;mov edx, edx
    sys.write

    mov eax, 4
    mov ebx, 1
    mov ecx, suprise3
    mov edx, suprise3L
    sys.write

done:

    mov eax, 1  
    mov ebx, 0  
    sys.exit
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文