我有以下程序从用户那里读取一位数整数:
SYS_READ equ 3
STDIN equ 0
section .data
msg db " eksi: "
msg_len equ $ - msg
section .bss
num resd 1
;----------------------
read_num:
push eax
push ebx
push ecx
push edx
mov edx, msg_len
mov ecx, msg
mov ebx, STDOUT
mov eax, SYS_WRITE
int 80h
mov edx, 4
mov ecx, num
mov ebx, STDIN
mov eax, SYS_READ
int 80h
sub dword [num], 2608 ; attention here
pop edx
pop ecx
pop ebx
pop eax
ret
在gdb
中观察变量的值,我发现值为2608 + entered_value
。我尝试过减去dword '0'
等但没有结果的事情。如果我需要 num
为4个字节,我该如何正确读取整数值?
答案 0 :(得分:1)
嗨,我对组装很新,并且遇到同样的问题,下面的文件显然不是最好的解决方案,但它对我来说至少对于最多9位数的数字,想法是在sys_read eax保存读取字节数之后因此可以使用此数字来获取数值,例如,如果输入为123,则数值为1 * 10 ^ 2 + 2 * 10 ^ 1 + 3 * 10 ^ 0
section .data
section .text
global _ipow
_ipow:
; input:
; ecx - exponent ( for some reason becoz of
; multiplication edx can't be used )
; output:
; eax - base ^ exponent
push ecx ; store ecx value
push edx ; store edx value ( mul )
mov eax, 1 ; zero exponent
start:
cmp ecx, 0 ; exit loop condition
jz finish ; we are done
mul dword [base] ; eax = eax * base
dec ecx ; next power
jmp start ; cycle
finish:
pop edx ; restore edx value
pop ecx ; restore ecx value
ret
global _start
_start:
nop
; read input value
mov eax, 0x03 ; sys_read
mov ebx, 0 ; stdin
mov ecx, buf ; memory block
mov edx, 10 ; number of bytes
int 0x80 ; syscall
; now eax holds the number of bytes read
dec eax ; discard new line character
; now eax holds the number of digits
mov ebx, 0 ; result
mov dword [base], 10 ; base 10 system
mov edx, ecx ; address
mov ecx, eax ; number of digits
S:
cmp ecx, 0 ; exit loop condition
jz F ; we are done
dec ecx ; exponent
call _ipow ;
push ebx ; store ebx
push edx ; store edx ( mul )
movzx ebx, byte [edx] ; ascii
sub ebx, '0'; numeric
mul ebx ; eax = eax * ebx
pop edx ; restore edx
pop ebx ; restore ebx
inc edx ; next character
add ebx, eax ; get the numeric value
jmp S ; cycle
F:
; at this point ebx holds the numeric value
mov eax, 0x1 ; sys_exit
mov ebx, 0x0 ; error code
int 0x80 ; syscall
section .bss
buf resb 10 ; 9 digits + '\n'
base resd 1 ; numeric system
文件使用
编译nasm -f elf -g -F dwarf atoi.asm
ld -m elf_i386 atoi.o -o atoi
但可能最好找一些其他解决方案如何正确编写atoi函数
答案 1 :(得分:0)
您只需要用户返回一个数字,因此您应该忽略缓冲区中的其他所有内容。使用示例中给出的缓冲区,您可以执行以下操作:
and dword[num],0FFh
sub dword[num],30h
此num
后将包含用户输入的数值。如果用户输入了字符,控制代码或任何非数字num
将高于9;您的进一步错误处理应考虑到这一点。