NASM - 分段错误和其他问题

发布于 2025-01-05 16:30:30 字数 3580 浏览 1 评论 0原文

这是我在这里发表的第一篇文章。我不确定我的格式是否正确,所以如果我搞砸了,请原谅我。

无论如何,这应该需要两个输入,将一个减半,另一个加倍,然后打印它们。它不应该正常工作,因为输入数据是字符,但输出仍然令人困惑:

[poise] [/home/a/a_mccr/terminal] > ./assignment2
Please enter a four-digit number, negative or positive
1234
The number you entered is
Half the entered value is
ÞH
Double the entered value is
x#      ÞH
Segmentation fault

它不会打印出我的输入(即 1234),然后每次输出都是 PH,然后是 X# PH。所有这些都表明输入没有被存储,但我不明白为什么。另外,我在程序结束时遇到了一个神秘的分段错误...救命!这是代码:

segment .data                   ;to compile use:        nasm -f elf assignment2.asm
                            ;                       ld -o assignment2 assignment2.o

    msg1 db 'Please enter a four-digit number, negative or positive', 0xA
    len1 equ $-msg1         ;length of 1st message
    msg2 db 'The number you entered is', 0xA
    len2 equ $-msg2         ;length of 2nd message
    msg3 db 'Half the entered value is', 0xA
    len3 equ $-msg3         ;length of 3rd message
    msg4 db 'Double the entered value is', 0xA
    len4 equ $-msg4         ;length of 4th message

segment .bss

    input2 resb 3           ;reserve 5 bytes for the entered number
    input resb 3            ;reserve 5 bytes for the entered number

segment .text
    global _start

_start:
    mov eax, 4      ;select kernel call 4, the write function
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, msg1   ;set the pointer to msg
    mov edx, len1   ;set the length to len
    int 0x80        ;call write function

    mov eax, 3      ;select the kernel read function
    mov ebx, 0      ;use the default input device (user txt input)
    mov ecx, input  ;pointer to input variable
    int 0x80        ;invoke kernel read function

    mov eax, 4      ;select kernel call 4, the write function
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, msg2   ;set the pointer to msg2
    mov edx, len2   ;set the length to len2
    int 0x80        ;call write function

    mov eax, 4      ;select kernel call 4, the write function
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, input  ;set the pointer to input
    int 0x80        ;call write function

    mov eax, [input]        ;move input to eax register
    mov ebx, [input]        ;move input to ebx register

    shr eax, 1      ;shift eax 1 place to the right
    shl ebx, 1      ;shift ebx 1 place to the left

    mov [input], eax        ;move contents of eax to input
    mov [input2], ebx       ;move contents of ebx to input2

    mov eax, 4      ;Write message about half
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, msg3   ;set the pointer to msg3
    mov edx, len3   ;set the length to len3
    int 0x80        ;call write function

    mov eax, 4      ;write contents of input
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, input  ;set the pointer to input
    int 0x80        ;call write function

    mov eax, 4      ;write message about double
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, msg4   ;set the pointer to msg4
    mov edx, len4   ;set the length to len4
    int 0x80        ;call write function

    mov eax, 4      ;write contents of input2
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, input2 ;set the pointer to input2
    int 0x80        ;call write function

_exit:
    mov eax, 1      ;standard exit
    mov ebx, 0      ;0 is normal
    int 0x80

this is my first ever post here. I'm not sure if I've done the formatting correctly, so forgive me if I've messed up.

Anyway, this is supposed to take two inputs, halve one and double the other, and then print them. It's not supposed to work properly, as the input data is in characters, but the output is nonetheless confusing:

[poise] [/home/a/a_mccr/terminal] > ./assignment2
Please enter a four-digit number, negative or positive
1234
The number you entered is
Half the entered value is
ÞH
Double the entered value is
x#      ÞH
Segmentation fault

It doesn't print out my input (which is 1234), and then every time the output is PH and then X# PH. All this indicates to me that the input is not being stored, but I can't figure out why. Also I get a mysterious segmentation fault at the end of my program... Help! Here's the code:

segment .data                   ;to compile use:        nasm -f elf assignment2.asm
                            ;                       ld -o assignment2 assignment2.o

    msg1 db 'Please enter a four-digit number, negative or positive', 0xA
    len1 equ $-msg1         ;length of 1st message
    msg2 db 'The number you entered is', 0xA
    len2 equ $-msg2         ;length of 2nd message
    msg3 db 'Half the entered value is', 0xA
    len3 equ $-msg3         ;length of 3rd message
    msg4 db 'Double the entered value is', 0xA
    len4 equ $-msg4         ;length of 4th message

segment .bss

    input2 resb 3           ;reserve 5 bytes for the entered number
    input resb 3            ;reserve 5 bytes for the entered number

segment .text
    global _start

_start:
    mov eax, 4      ;select kernel call 4, the write function
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, msg1   ;set the pointer to msg
    mov edx, len1   ;set the length to len
    int 0x80        ;call write function

    mov eax, 3      ;select the kernel read function
    mov ebx, 0      ;use the default input device (user txt input)
    mov ecx, input  ;pointer to input variable
    int 0x80        ;invoke kernel read function

    mov eax, 4      ;select kernel call 4, the write function
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, msg2   ;set the pointer to msg2
    mov edx, len2   ;set the length to len2
    int 0x80        ;call write function

    mov eax, 4      ;select kernel call 4, the write function
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, input  ;set the pointer to input
    int 0x80        ;call write function

    mov eax, [input]        ;move input to eax register
    mov ebx, [input]        ;move input to ebx register

    shr eax, 1      ;shift eax 1 place to the right
    shl ebx, 1      ;shift ebx 1 place to the left

    mov [input], eax        ;move contents of eax to input
    mov [input2], ebx       ;move contents of ebx to input2

    mov eax, 4      ;Write message about half
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, msg3   ;set the pointer to msg3
    mov edx, len3   ;set the length to len3
    int 0x80        ;call write function

    mov eax, 4      ;write contents of input
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, input  ;set the pointer to input
    int 0x80        ;call write function

    mov eax, 4      ;write message about double
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, msg4   ;set the pointer to msg4
    mov edx, len4   ;set the length to len4
    int 0x80        ;call write function

    mov eax, 4      ;write contents of input2
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, input2 ;set the pointer to input2
    int 0x80        ;call write function

_exit:
    mov eax, 1      ;standard exit
    mov ebx, 0      ;0 is normal
    int 0x80

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

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

发布评论

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

评论(2

听风念你 2025-01-12 16:30:30

当您读取输入时,您似乎忘记指定要读取的长度:

mov eax, 3      ;select the kernel read function
mov ebx, 0      ;use the default input device (user txt input)
mov ecx, input  ;pointer to input variable
int 0x80        ;invoke kernel read function

假设 edx 的旧值将是 read 的长度(2)——这将远远长于您的输入空间。 (还有五个字节?当然看起来很奇怪。另外,注释似乎与代码不匹配,但这可能是我的无知而不是你的代码。)

When you're reading input, it appears that you forgot to specify a length to read:

mov eax, 3      ;select the kernel read function
mov ebx, 0      ;use the default input device (user txt input)
mov ecx, input  ;pointer to input variable
int 0x80        ;invoke kernel read function

I presume that the old value of edx will be the length of read(2) -- which will be far longer than your input space. (And five bytes? Sure seems odd. Also, the comment doesn't seem to match the code, but that could be my ignorance more than your code.)

缺⑴份安定 2025-01-12 16:30:30

让我说得对:

  1. 你读取一个字符串作为输入
  2. 你将它放入寄存器中(实际上 32 位寄存器的宽度足以容纳 4 个字符的字符串)
  3. 你将字符串重新解释为整数(这里你实际上需要 将它从十进制转换为二进制)
  4. 您将其减半/加倍
  5. 您将无意义的减半字符流发送到输出
  6. 您在屏幕上收到垃圾。

在输入和输出之前,您需要将收到的 ASCII 字符串从十进制转换为二进制,然后再转换回来。如果您不使用 atoi() 或类似的,您可以编写自己的版本,实际上并不那么难。

您需要为字符串保留更多字节,32 位数字最多可能有 10 个字符长。如果您这样做了,您可能自己已经看到了错误,因为您可能会发现很难将 10 字节字符串压缩到 32 位寄存器中。

Let me get that right:

  1. You read a string as input
  2. You put it in a register (actually a 32 bit register is just wide enough to hold a 4 char string)
  3. You reinterpret the string a integer (here you actually need to convert it from decimal to binary)
  4. You halve/double it
  5. You send the meaningless stream of halved chars to the output
  6. You receive garbage on the screen.

You need to convert the ASCII string you receive from decimal to binary and back before input and output. If you don't to use atoi() or similar, you can write your own version, it isn't actually that hard.

You need to reserve more bytes for the strings, a 32 bit number may be up to 10 chars long. Would you have done that, you probably have seen there error by yourself, because you might have find it difficult to squeeze a 10 byte string into a 32 bit register.

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