我需要编写一个程序,将加载的字符串更改为十进制表示法并在控制台上写入我们收到的内容,现在在此代码中只有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
答案 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倍,为所有数字腾出空间,在包括任何空格之前。