2013-03-24 133 views
0

我今天正在做一些編碼,並在其他主題的幫助下,我試圖做我自己的程序。它的想法是將我在開始時的值(ascii)改爲正常值。所以,我想什麼控制檯看到:32位Linux x86彙編代碼和垃圾在輸出

  1. 號[A-1,...,Z-26]

輸出,當我進入一個是1, B.將2等 我得到的輸出是噸垃圾..

這裏是我的代碼:

SYSCALL = 0X80 
SYSEXIT = 1 
SYSREAD = 3 
SYSWRITE = 4 
STDIN = 0 
STDOUT = 1 

.data 
.align 32 

NUMBER_MAXLEN = 2 
NUMBER: .space NUMBER_MAXLEN 
NUMBER_LEN: .long 0 

MSG_NUMBER: .ascii "Number [A-1, .., Z-26] " 
MSG_NUMBER_LEN = . - MSG_NUMBER 

.text 
.global _start 

_start: 

#show 
mov $SYSWRITE, %eax 
mov $STDOUT, %ebx 
mov $MSG_NUMBER, %ecx 
mov $MSG_NUMBER_LEN, %edx 
int $SYSCALL 

#read 
mov $SYSREAD, %eax 
mov $STDIN, %ebx 
mov $NUMBER, %ecx 
mov $NUMBER_MAXLEN, %edx 
int $SYSCALL 

#length 
sub $1, %eax 
mov %eax, NUMBER_LEN 

#Change to normal value 
xor %eax, %eax 
movb NUMBER, %al 
sub $'A', %al 
add $1, %al 
movb %al, NUMBER 

#Print 
mov $SYSWRITE, %eax 
mov $STDOUT, %ebx 
mov $NUMBER, %ecx 
mov $NUMBER_LEN, %edx 
int $SYSCALL  

END: 
mov $SYSEXIT, %eax 
int $SYSCALL 

我幹什麼什麼克錯了?怎麼可能修好?

+0

我下NUMBER檢查(使用gdb)值,和後(子$ 'A',%人 加$ 1%人 MOVB%人,NUMBER),它像68000,而不是1 ..爲什麼? – 2013-03-24 15:18:17

回答

0

系統調用(4)簡單地打印字符串,它不作爲printf函數。因此,在打印之前,您需要將數字轉換爲其字符串表示形式。

這裏的說明一些pseduo代碼怎麼可以做:

char buffer[10]; 
char *p = &buffer[9]; 

*p = 0; // NULL terminator 
do { 
    p--; 
    *p = (number % 10) + '0'; 
    number /= 10; 
} while (number != 0); 

print(buffer); 
+0

此代碼不能幫助我..我不明白這一點。你能解釋一下嗎,還是隻有轉換的方法? – 2013-03-24 15:36:24

+0

它所做的只是以倒數的順序將'0'..'9'中的字符重複添加到字符串緩衝區中。如果數字是25,它會向緩衝區寫入'5',然後將25除以10得到2.因此,在下一次迭代時,它將'2'寫入緩衝區,將2除以10得到0,停止。此時的緩衝區包含'2','5'(以及在開始處添加的NULL終止符),即字符串「25」。 – Michael 2013-03-24 16:38:02

+0

除了itoa問題,'movl $ NUMBER_LEN,%edx'將'NUMBER_LEN'的地址移動到'$ edx'中 - 打印太多字符。失去'$'。這就是爲什麼你得到「噸」的垃圾,而不是一個或兩個字符...... – 2013-03-24 19:01:08

0

如果用戶輸入「Z」,要打印「26」?你可以使用查找表,或者自己做一些轉換。 INTEL/NASM格式:

%define SYSCALL 0X80 
%define SYSEXIT 1 
%define SYSREAD 3 
%define SYSWRITE 4 
%define STDIN 0 
%define STDOUT 1 

%define NUMBER_MAXLEN 2 
section .data 

MSG_NUMBER: db "Number [A-1, .., Z-26] ", 0 
MSG_NUMBER_LEN equ $ - MSG_NUMBER 

section .bss 

NUMBER:   resb NUMBER_MAXLEN 
NumToPrint  resb 3 
NUMBER_LEN:  resd 1 

section .text 
global main 

main: 

;show 
    mov  eax, SYSWRITE 
    mov  ebx, STDOUT 
    mov  ecx, MSG_NUMBER 
    mov  edx, MSG_NUMBER_LEN 
    int  SYSCALL 

;~ #read 
    mov  eax, SYSREAD 
    mov  ebx, STDIN 
    mov  ecx, NUMBER 
    mov  edx, NUMBER_MAXLEN 
    int  SYSCALL 

;~ #length 
    sub  eax, 1 
    mov  NUMBER_LEN, eax 

;~ #Change to normal value 
    movzx eax, byte [NUMBER] 
    push eax 
    call IsValidChar 
    test eax, eax 
    js  main       ; not valid input, repeat prompt 

    push NumToPrint 
    push eax 
    call dwtoa       ; convert to ASCII 

;~ #Print 
    mov  edx, eax 
    mov  eax, SYSWRITE 
    mov  ebx, STDOUT 
    mov  ecx, NumToPrint   
    int  SYSCALL  

End: 
    mov  eax, SYSEXIT 
    int  SYSCALL 

;~ #########################################  
IsValidChar: 
    mov  eax, [esp + 4] 

.0to9: 
    cmp  eax, "0" 
    jb  .NoGood 
    cmp  eax, "9" 
    ja  .AtoZ 
    jmp  .NoGood 

.AtoZ: 
    cmp  eax, "A" 
    jb  .NoGood 
    cmp  eax, "Z" 
    ja  .atoz 
    sub  eax, 64       ; convert letter index to number equiv. 
    jmp  .Done 

.atoz: 
    cmp  eax, "a" 
    jb  .NoGood 
    cmp  eax, "z" 
    ja  .NoGood 
    sub  eax, 96       ; convert letter index to number equiv. 
    jmp  .Done 

.NoGood: 
    xor  eax, eax 
    dec  eax 
.Done: 
    ret  4 

您需要創建自己的dwtoa(DWORD到ASCII)。

enter image description here