汇编程序将字符串加载到十进制表示法

时间:2015-03-30 10:21:45

标签: assembly x86

我需要编写一个程序,将加载的字符串更改为十进制表示法并在控制台上写入我们收到的内容,现在在此代码中只有echo工作,如何在内存中移动以更改我们收到的字符串?

.align 32

SYSEXIT = 1
SYSREAD = 3
SYSWRITE = 4
STDOUT = 1
STDIN =0
EXIT_SUCCESS = 0

.data

    bufor: .space 1000
    bufor_len = 10
    num: .int =10
    numm: .int =1


.text

    text: .ascii "Podaj ciag znakow"
    text_len = . - text

.global _start
_start:

    mov $SYSWRITE, %eax
    mov $STDOUT, %ebx
    mov $text, %ecx
    mov $text_len, %edx
    int $0x80

    mov $SYSREAD, %eax
    mov $STDIN, %ebx
    mov $bufor, %ecx
    mov $bufor_len, %edx
    int $0x80


ety_1:
    mov $bufor, %eax
    mov $al, %ecx
    imul $num, %ecx
ety_2:

    shr $numm, %eax
    mov $al, %ebx
    imul $num, %ebx
    add %ebx, %eax
    cmp %al,lf
    jne ety_2

    int $0x80

    mov $SYSWRITE, %eax
    mov $STDOUT, %ebx
    mov $bufor, %ecx
    mov $bufor_len, %edx
    int $0x80

    mov $SYSEXIT, %eax
    mov $EXIT_SUCCESS, %ebx
    int $0x80

1 个答案:

答案 0 :(得分:0)

您的角色已经是ASCII格式。您正在寻找的只是一种以不同方式输出它们的方法。

通常,要打印数字的数字表示,您需要提取单个数字(对于十进制表示,可以通过重复除以10并检查余数来完成)并为{添加ASCII代码{1}}给他们,给你可打印的字符。然后你只输出可打印的字符。

这是一种在nasm格式x86_64汇编中执行此操作的相当粗略的方法,利用了可打印的ASCII字符可以表示为不少于两个且不超过三个十进制数字的事实:

'0'

带输出:

global _start

STDIN           equ     0
STDOUT          equ     1
STDERR          equ     2

SYSCALL_READ    equ     0
SYSCALL_WRITE   equ     1
SYSCALL_EXIT    equ     60

ASCII_ZERO      equ     0x30
ASCII_SPACE     equ     0x20


        section .rodata

src     db      'Podaj ciag znajow', 0x00       ;  String to convert
newline db      0x0a, 0x00                      ;  String for print_newline


        section .data

ach     db      'XXX ', 0x00                    ;  String for print_ascii


        section .text

;  Exits with success code.

exit_success:
        mov     rax, SYSCALL_EXIT
        mov     rdi, 0
        syscall


;  Calculates length of null-terminated string.
;  Arg 1 - address of string.
;  Returns - length of string.

string_length:
        push    rbp                     ;  Set up stack
        mov     rbp, rsp

        mov     rax, -1                 ;  Set character count to -1
        xor     rdx, rdx                ;  Zero register for character

.slloop:
        inc     rax                     ;  Increment character count
        mov     dl, BYTE [rdi+rax]      ;  Load character to dl
        cmp     dl, 0                   ;  If it's not the null character...
        jne     .slloop                 ;  ...keep counting.

        leave                           ;  Return character count
        ret


;  Outputs a null-terminated string to standard output.
;  Arg 1 - address of string.
;  No return value.

put_string:
        push    rbp                     ;  Set up stack
        mov     rbp, rsp
        sub     rsp, 16

        mov     [rbp-16], rdi           ;  Save address prior to func call

        call    string_length           ;  Get length of string
        mov     rdi, STDOUT             ;  First arg to write syscall
        mov     rsi, [rbp-16]           ;  Restore address to second arg
        mov     rdx, rax                ;  Third arg to write syscall
        mov     rax, SYSCALL_WRITE      ;  Load system call number
        syscall                         ;  Make system call

        leave                           ;  Return
        ret


;  Prints a numeric representation of a character's ASCII code.
;  Arg 1 - the character.
;  No return value.

print_ascii:
        push    rbp                     ;  Set up stack
        mov     rbp, rsp

        mov     rax, rdi                ;  Move character to rax
        mov     rcx, 10                 ;  Load rcx with divisor

        ;  Extract least significant digit

        xor     rdx, rdx                ;  Zero high-order bits for idiv
        idiv    rcx                     ;  Divide character by ten
        add     rdx, ASCII_ZERO         ;  Add '0' to remainder
        mov     BYTE [ach+2], dl        ;  Write third digit to string

        ;  Extract two most significant digits from quotient

        xor     rdx, rdx                ;  Zero high-order bits for idiv
        idiv    rcx                     ;  Divide by ten
        add     rax, ASCII_ZERO         ;  Add '0' to new quotient
        add     rdx, ASCII_ZERO         ;  Add '0' to new remainder

        ;  Write digits to string and print

        mov     BYTE [ach], al          ;  Write first digit to string
        mov     BYTE [ach+1], dl        ;  Write second digit to string

        lea     rdi, [ach]              ;  Load address of string
        lea     rsi, [ach+1]            ;  Prepare for conditional move
        cmp     rax, ASCII_ZERO         ;  If most significant digit is zero...
        cmove   rdi, rsi                ;  ...don't print it
        call    put_string              ;  Print ASCII representation

        leave                           ;  Return
        ret


;  Prints a newline
;  No arguments, no return value.

print_newline:
        push    rbp                     ;  Set up stack
        mov     rbp, rsp

        lea     rdi, [newline]          ;  Load address of newline string
        call    put_string              ;  Print it

        leave                           ;  Return
        ret


;  Entry point

_start:
        mov     rbp, rsp                ;  Set up stack
        sub     rsp, 16                 ;  Set up some local storage
        lea     rdi, [src]              ;  Load address of string

        call    put_string              ;  Print plain string first
        call    print_newline           ;  For tidy output
        lea     rdi, [src]              ;  Reload address after func call

.mainloop:
        movsx   rax, BYTE [rdi]         ;  Move a byte to rax
        cmp     rax, 0                  ;  If it's zero...
        je      .loopdone               ;  ...then we're done.

        mov     [rbp-16], rdi           ;  Save current string address
        mov     rdi, rax                ;  Pass character to function
        call    print_ascii             ;  Print representation of character
        mov     rdi, [rbp-16]           ;  Restore current string address
        inc     rdi                     ;  Increment current string address
        jmp     .mainloop               ;  Loop again

.loopdone:
        call    print_newline           ;  For tidy output
        call    exit_success            ;  Exit

显然,如果你想真正修改原始字符串,你必须有更多的空间,因为你可以指望长度增加2到3倍,为所有数字腾出空间,在包括任何空格之前。