2012-02-16 40 views
1

這是我第一次在這裏發佈。我不確定我是否正確地完成了格式化,所以請原諒我,如果我搞砸了。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 

回答

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空間。 (?和字節當然似乎很奇怪此外,評論似乎並不匹配的代碼,但可能是我的無知比你的代碼更。)

+0

有些評論不完全正確,因爲我有時在編輯一行後忘記更新它們。我實際上使用了3個字節,因爲我最多需要5個4位點(負號和4個整數)。我應該怎樣設定長度? – mavix 2012-02-16 02:56:10

+0

哦,我想我不必告訴它的長度,如果它是一個實例變量(TA沒有在他給我們的示例代碼中) – mavix 2012-02-16 02:57:40

+1

啊哈,三個字節是_definitely_不足以容納四個字節'1234 ' - 而且,自從我這樣做以來已經過了很多年了,但在您敲'^ D'結束輸入之前,可能需要'\ n'的空間。到目前爲止,它仍然是純文本。 – sarnold 2012-02-16 03:06:49

0

讓我得到這個權利:

  1. 你讀一個字符串作爲輸入
  2. 你把它放在一個寄存器(實際上是一個32位的寄存器只是寬度足以容納4個字符的字符串)
  3. 您重新詮釋字符串整數(在這裏你真正需要從十進制轉換爲二進制)
  4. 您減半/加倍
  5. 您減半字符的意義流發送到輸出
  6. 你在屏幕上收到垃圾。

您需要將您從十進制接收到的ASCII字符串轉換爲二進制,並在輸入和輸出之前將其返回。如果你不使用atoi()或類似的,你可以編寫自己的版本,但實際上並不那麼難。

您需要爲字符串保留更多字節,32位數字可能長達10個字符。你會這樣做嗎,你可能已經看到了你自己的錯誤,因爲你可能發現很難將一個10字節的字符串壓縮到一個32位的寄存器中。

+0

我知道該程序不會按照它應有的方式運行。我的教授認爲他正在教授數據類型的教訓,指派我們編寫一個不起作用的程序。我認爲他的教學方法可以使用一些工作,但無論哪種方式,我真正的問題是: – mavix 2012-02-17 19:15:15

+0

1.我得到了分段錯誤。我不知道這意味着什麼。你是否在說這是因爲32位寄存器不夠大以至於無法存儲我正在操作的數據? 2.它永遠不會打印存儲在輸入變量(我指的是第二次寫函數調用)中的數據。我無法弄清楚,爲了我的生活,爲什麼會這樣。 – mavix 2012-02-17 19:17:27

+0

和3.轉移後,它似乎總是打印相同的東西,理論上每次都應該是一組不同的無意義角色,不是? – mavix 2012-02-17 19:18:21