输出时32位Linux x86汇编代码和垃圾箱

时间:2013-03-24 14:49:55

标签: assembly x86

我今天正在做一些编码,在其他主题的帮助下,我试着做自己的程序。它的想法是将我在开始(它的ascii)放置的值更改为正常值。那么,我想在控制台中看到什么:

  1. 编号[A-1,..,Z-26] A
  2. 1
  3. 输入A时的输出为1,B为2,等等。 输出I GET是大量垃圾..

    这是我的代码:

    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
    

    我做错了什么?怎么能好......修好了?

2 个答案:

答案 0 :(得分:0)

__nr_write系统调用(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);

答案 1 :(得分: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