【问题标题】:NASM division using variables instead of actual valuesNASM 除法使用变量而不是实际值
【发布时间】:2018-01-30 21:35:55
【问题描述】:

我正在学习一些在 Linux 上使用 NASM 的基本算术。我需要使用变量 NUMBER1 和 NUMBER2 来划分两个数字。如果我输入实际值而不是变量,我的代码就可以工作。例如,如果我输入“6”而不是 NUMBER2 和“2”而不是 NUMBER1,程序会进行除法并给出 3 的答案。 使用变量运行代码会产生 FLOATING EXCEPTION (CORE DUMPED)。请解释如何正确使用此代码中的变量? 调试时,我发现问题出在 DIV 行。谢谢!

 section .text

global main ;must be declared for using gcc

main: ;tell linker entry point
mov ax,[NUMBER2]
sub ax, '0'
mov bl, [NUMBER1]
div bl
add ax, '0'
mov [res], ax
mov ecx,msg
mov edx, len
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
nwln
mov ecx,res
mov edx, 1
 mov ebx,1 ;file descriptor (stdout)
 mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel

section .data
NUMBER1: dw 2
NUMBER2: dw 6
msg db "The result is:", 0xA,0xD
len equ $- msg

segment .bss
res resb 1

【问题讨论】:

  • sub ax, '0' -- 为什么会出现在这里?您将原始 6 存储在数据段中,而不是 ascii 字符 6
  • 我正在使用 NASM 文档中的这个示例,我相信这是因为剩余部分。

标签: linux math assembly nasm division


【解决方案1】:

因为给定的示例应该处理数字的 ASCII 代码,而不是数字本身。如果您输入6 而不是'6'6 - '0' 的计算结果为65494(不是6)。如果您尝试进一步除以2,处理器将无法将商存储在ax 寄存器的下半部分。

如果您不打算将结果输出到控制台,而只是尝试使用汇编程序了解一个字节整数的除法是如何工作的,请选择您最喜欢的调试器,在除法运算后放置断点并享受您的结果。

section .text

global main ;must be declared for using gcc

main: ;tell linker entry point
mov ax,[NUMBER2]
mov bl, [NUMBER1]
div bl
nop ; quotient at al, remainder at ah
; remove nop instruction if your code is larger than few lines
; place output code here

section .data
NUMBER2: dw 6 ; dw means two bytes
NUMBER1: db 2 ; db means one byte

segment .bss
res resb 1

【讨论】:

  • 为什么div后面有nop指令?如果您想让设置断点变得容易,请在div 之后放置一个标签,或者只需在div 之前设置一个断点并单步执行它(这样您就可以在它运行之前/之后查看寄存器值)。但是,是的,答案是 sub 换行,然后大数的无符号 div 2 溢出商,这引发了 #DE,causing Linux to deliver SIGFPE。 (因为与大多数整数运算不同,div 溢出陷阱而不是包装。)
  • @PeterCordes nop 指令是断点的占位符,通常比任何标签都短。
  • 但它汇编成可执行文件中的指令!如果您出于某种原因想要紧凑的源代码而不是干净/高效的 asm,那么 bp: 也很短。此外,它还可以让您输入b bp,而不必查找nop 的地址或行号(如果您使用的是文本模式gdb,那么您不能只单击未标记的说明)。
  • @PeterCordes 我编辑了关于该指令的答案。我比 Linux 更熟悉 Windows 汇编调试,所以你的问题。
  • 您永远不需要nop。即使您在div 之后创建了一个带有垃圾的不完整程序,您也可以单步跳过div,以便在接下来的任何事情上停止执行。有一个 NOP 没有用或不重要。如果你想放任何东西,放xor ebx,ebx / mov eax,1 / int 0x80 ; sys_exit(0)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 2011-10-18
  • 2021-12-16
相关资源
最近更新 更多