【发布时间】:2014-10-29 21:10:11
【问题描述】:
我有一个在我看来相当简单的项目。向用户询问 0-255 和 2-9 之间的基数。并在该基地输出。我计划简单地执行一个通常的除法算法并获取余数,推入堆栈,然后弹出以获取相反的顺序以输出回用户。然而,在插入一些打印调试语句后,其余部分的输出非常奇怪
; Run using nasm -f elf -g -F stabs proj4.asm
; gcc -o proj4 proj4.o -m32
; To execute type proj4
%macro SAVE_REGS 0
push eax
push ecx
push edx
%endmacro
%macro RESTORE_REGS 0
pop edx
pop ecx
pop eax
%endmacro
%macro CALL_PUTS 1
push %1
call puts
add esp, 4
%endmacro
%macro CALL_SCANF 2
push %1
push %2
call scanf
add esp, 8
%endmacro
%macro CALL_PRINTF1 1
push %1 ;The address of the string to print
call printf
add esp, 4
%endmacro
%macro CALL_PRINTF2 2
push %1 ;The formatted string with a %char place holder
push %2 ;The item to place into the place holder
call printf
add esp, 8
%endmacro
SECTION .data
prmptNumMsg: db "Enter a number between 0 and 255: ", 0
prmptBaseMsg: db "Enter a base between 2 and 9: ", 0
remShow: db 'The the remainder is: %d', 10, 0
numShow: db 'The number is %d', 10, 0
baseShow: db 'The base is %d', 10, 0
printed: db 'Looped in division method', 10, 0
poped: db 'Looped in pop method',10, 0
ansShow: db '8d', 10, 0
numFormat db '%d', 0
stringFormat db '%s', 0
SECTION .bss
numVal resd 1
baseVal resd 1
ans resd 9
i resd 1
n resd 1
j resd 1
SECTION .text
global main
extern puts
extern scanf
extern printf
main:
push ebp ; Set up stack frame for debugger
mov ebp, esp
push ebx
push esi
push edi
;Everything before this is boilerplate
getInt:
CALL_PRINTF1 prmptNumMsg
;push numVal
;push numFormat
;call scanf
;add esp, 8
CALL_SCANF numVal, numFormat
mov eax, dword[numVal]
mov ebx, dword 0 ;check below 0
cmp eax, ebx
jb getInt
mov eax, dword[numVal]
mov ebx, dword 255 ;check above 255
cmp eax , ebx
ja getInt
;VALID INTEGER PAST THIS POINT
getBase:
CALL_PRINTF1 prmptBaseMsg
CALL_SCANF baseVal, numFormat
mov eax, dword[baseVal]
mov ebx, dword 0
cmp eax, ebx
jb getBase
mov eax, dword[baseVal]
mov ebx, dword 9
cmp eax, ebx
ja getBase
;END GETBASE
;VALID BASE NUMBER PAST THIS POINT
mov eax, dword[numVal]
mov [n], eax ;set n to the current number value
CALL_PRINTF2 eax, numShow
mov eax, dword 0
mov [i], eax
mov eax, dword[baseVal]
CALL_PRINTF2 eax, baseShow
doDivision:
;CALL_PRINTF1 printed
xor edx, edx
mov eax, dword[n]
mov ebx, dword[baseVal]
div ebx ;edx = remainder eax = quotient
mov [n], eax ;save quotient
CALL_PRINTF2 eax, numShow
CALL_PRINTF2 edx, remShow
;push edx ;save remainder on stack to pop in reverse order later
;mov [n], eax ;move quotient to eax
mov ebx, dword[i]
inc ebx
mov [i], ebx ;i++
;mov eax, [i]
mov ecx, dword 8
cmp ebx, ecx
jb doDivision
;END DO DIVISION
end:
;Everything after this is boilerplate
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret
当程序运行时,我的输出如下
Enter a number between 0 and 255: 105
Enter a base between 2 and 9: 4
The number is 105
The base is 4
The number is 26
The the remainder is: 13144896
The number is 6
The the remainder is: 13144896
The number is 1
The the remainder is: 13144896
The number is 0
The the remainder is: 13144896
The number is 0
The the remainder is: 13144896
The number is 0
The the remainder is: 13144896
The number is 0
The the remainder is: 13144896
The number is 0
The the remainder is: 13144896
我希望它循环 8 次,这是正确的,每个 div 操作的商都是正确的,但是对于将保存在 edx 中的其余部分,我得到了疯狂的数字。我不明白这是什么原因造成的。
【问题讨论】:
-
改变这两行的顺序,看看会发生什么。然后找出原因。分割后的
CALL_PRINTF2 eax, numShow和CALL_PRINTF2 edx, remShow。 -
什么? 你的意思是你必须先计算余数才能打印?谁听说过这种废话。首先打印未初始化的值,然后尝试计算……一些东西……很好,把它写成带有一点解释的答案形式,OP 应该接受。
-
进一步提示:
printf返回一个值。它放在哪里?顺便说一句,问题看起来very familiar(虽然被问到的问题更具体)。