NASM - 分段故障和其他问题

时间:2012-02-16 02:47:13

标签: assembly segmentation-fault nasm

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

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

[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

2 个答案:

答案 0 :(得分:1)

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

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)的长度 - 这将远远超过input空间。 (还有五个字节?当然看起来很奇怪。此外,评论似乎与代码不匹配,但这可能比我的代码更无知。)

答案 1 :(得分:0)

让我做对了:

  1. 您读取字符串作为输入
  2. 你把它放在一个寄存器中(实际上32位寄存器的宽度足以容纳4个字符串)
  3. 您将字符串重新解释为整数(此处您实际上需要从十进制转换为二进制)
  4. 你将它减半/加倍
  5. 您将无意义的减半字符流发送到输出
  6. 你在屏幕上收到垃圾。
  7. 您需要将从十进制接收的ASCII字符串转换为二进制并在输入和输出之前返回。如果你不使用atoi()或类似的,你可以编写自己的版本,实际上并不那么难。

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