我写了一个程序,用一个long int和一个int数组做除法和mod运算。当我想写我的除法运算的结果,但我不能。我不能找出问题,但我认为我使用了错误的数据部分的寄存器分配过程。请帮助我。我认为我从数据部分调用数组和int数组错误,或者我有问题与寄存器使用。这是我的代码:
global _start
section .text
_start:
mov r9, number ; rdi stores adress of number array
mov r12, 0 ; get number of k for determine index of number array
L3: ; function begin
mov r15, 0 ; get number of i because using i of loop register
mov r14, [digits] ; get number of digits
mov r13, [r9 + r12*4] ; get array number for using array adress. We use 4*k because we take k. index of array
syscall
cmp r13, 0 ; determine number is negative or positive
jl L2 ; if it is negative we goto else part for print minus
; print blank otherwise we print blank
mov rax, 1
mov rdi, 1
mov rsi, blank
mov rdx, 1
syscall
jmp L1 ; after printing, jump L1 statement
L2: ; if number is negative continiuos here so Else part
; print minus
mov rax, 1
mov rdi, 1
mov rsi, minus
mov rdx, 1
syscall
neg r13 ; convert the negative number to positive number
L1: ; into the loop
; division operation digit = (number/digits)
mov rax, r13 ; dividend
cqo
mov rbx, r14 ; divisor
idiv rbx ; after the div operation rbx store division
mov r10, rax ; result is egual digit (r10)
; print digit
add rsp , 8
add r10, 48
mov rax , 1
mov rdi, 1
push r10
mov rsi, rsp
mov rdx, 1
syscall
; mod operation number = number % digits
mov rax, r13 ; dividend
cqo
mov rbx, r14 ; divisor
xor rdx, rdx ; rdx which store reminder be zero
idiv rbx ; after the div operation rbx store division
mov r13, rdx ; rdx store reminder and reminder egual number
; division operation digits = (digits/10)
mov rdx, 1
mov rax, r14 ; dividend
mov rbx, 10 ; divisor
div rbx ; after the div operation rbx store division
mov r14, rbx ; result is egual digit (r14)
inc r15 ; increment the loop register
cmp r15, 9 ; compare loop register with 9 so loop work 8 times
jl L1 ; if loop register less than 9 return loop
; print new line
mov rax, 1
mov rdi, 1
mov rsi, newline
mov rdx, 1
syscall
inc r12 ; increment k by 1
cmp r12, 8 ; compare k with numberCount
jl L3 ; if k less than numberCount, goto L3 that is begining write9digits function
Exit: ; if array index(k) greater than numberCount work Exit
mov rax, 60 ; system call for exit
xor rdi, rdi ; exit code 0
syscall ; invoke operating system to exit
section .data
newline db 10 ; note the newline at the end
blank db ' '
minus db '-'
i dd 0
k dd 0
digits dd 100000000
number dd 321762410, 9, 2943018, 0, 19372039, 18, -76241, -208424
这段代码将打印出
00000000
0�0000000
0�0000000
0�0000000
000000000
-0�0000000
-0�0000000
0_0000000
但根据我的c代码结果必须是这样的:
321762410
000000009
002943018
000000000
019371039
000000018
-000076241
-000208424
我尝试使用qword转换take integer,但没有任何变化。在我将整数的格式更改为十六进制格式后,没有任何变化。最后,我尝试更改[digits]和[r9 + r12*4]。
mov r14, [digits] ; get number of digits
mov r13, [r9 + r12*4] ; get array number for using array adress. We use 4*k
如果我将[digits]改为5,将[r9 + r12*4]改为21,则输出如下:
mov r14, 5 ; get number of digits
mov r13, 21 ; get array number for using array adress. We use 4*k
400000000
400000000
400000000
400000000
400000000
400000000
400000000
400000000
1条答案
按热度按时间whitzsjs1#
问题揭示审核
R9和RDI不一样。修改注解。R9不是被call-clobbered了吗?(请看我下面的改进代码,它没有使用R9)
这里加载的是除数的初始值(100,000,000)。而 digits 是用双字定义的,因此加载这个值需要写
mov r14d, [digits]
或movzx r14, dword [digits]
。数组元素是双字,所以 *4比例因子是可以的,但R9是一个qword寄存器,所以你应该加载带有符号扩展的值:
或者,你可以将数组元素定义为qwords,然后写:
您有一条多余的SYSCALL指令。要删除。
处理负输入的代码如果写成这样看起来会更好:
首先将除数从R14移动到RBX中没有任何好处。您可以简单地写:
idiv r14
。在 print digit 中,存在
add rsp, 8
操作,用于将push r10
值从堆栈中删除。显然,您只能在push执行后执行此操作。在 *mod操作 * 中,
xor rdx, rdx
会破坏执行cqo
的工作量,这在使用idiv
之前是正常的。您可以 * 使用xor rdx, rdx
,但要与div
(无符号除法)结合使用。在将除数减少10倍的部分中,您已经引入了将RDX设置为1的错误,在使用
div
之前应该将其归零。此外,除法的商在RAX中,因此将其移动到R14。改进代码
代码不是最佳的。使用收缩除数的数字转换比使用固定除数10和向后存储的成本更高。