【问题标题】:NASM assembly number to base conversionNASM 程序集编号到基础转换
【发布时间】: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, numShowCALL_PRINTF2 edx, remShow
  • 什么? 你的意思是你必须先计算余数才能打印?谁听说过这种废话。首先打印未初始化的值,然后尝试计算……一些东西……很好,把它写成带有一点解释的答案形式,OP 应该接受。
  • 进一步提示:printf 返回一个值。它放在哪里?顺便说一句,问题看起来very familiar(虽然被问到的问题更具体)。

标签: assembly nasm base


【解决方案1】:

当您调用例程(例如:printf)时,有一些规则可以控制其工作方式。例如,您是否将参数放在堆栈上?或者将它们传递到寄存器中?您是否从左到右推送参数?还是从右到左?调用者是否将参数从堆栈中弹出?还是被调用者?返回值将位于何处?

对于您的问题,最重要的是,被调用者是否需要确保所有寄存器在返回时都具有相同的值?或者它可以覆盖其中的一些?

这些问题的答案称为“调用约定”(有时也称为 ABI)。而且答案不止一个。例如 cdecl、pascal 和 fastcall 都是 x86 上常见的调用约定,它们都以略有不同的方式回答这些问题。

相信你会发现printf就是cdecl。考虑到这一点,您可以查看http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl。这应该有助于您了解本示例中 edx 发生的情况。

【讨论】:

  • OP 提供了带有需要解决的简单特定问题的特定代码。虽然您的答案内容通常是正确的,但它无法解决代码中CALL_PRINTF2 调用顺序的问题。此外,在需要特定帮助时让 OP 去追逐一般信息可能会给问题带来更多混乱,而不是让它变得更好。有时,在选择是否发表评论或留下答案时,谨慎是勇气的更好部分。
猜你喜欢
  • 2018-09-08
  • 1970-01-01
  • 2013-07-14
  • 2020-07-26
  • 2013-10-22
  • 1970-01-01
  • 2015-12-26
  • 1970-01-01
  • 2022-01-19
相关资源
最近更新 更多