我写了一个程序,用一个 long int 和一个 int 数组做除法和模运算。当我想写我的除法运算结果但我不能。我无法找出问题所在,但我认为我错误地使用了数据部分的寄存器分配过程。请帮我。我认为我在数据部分错误地调用了 array 和 int array,或者我在使用寄存器时遇到了问题。这是我的代码:
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 转换取整数但没有任何改变。在我将整数格式更改为十六进制格式后,没有任何改变。最后,我尝试更改 [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
mov r9, number ; rdi stores adress of number array
R9 与 RDI 不同。更改评论。
mov r14, [digits] ; get number of digits
这里加载的是除数的初始值(100,000,000)。并且 digits 被定义为一个双字,因此加载这个值需要写
mov r14d, [digits]
或 movzx r14, dword [digits]
.
mov r13, [r9 + r12*4] ; get array number for using array adress. We use 4*k because we take k. index of array
数组元素是双字,所以 *4 比例因子很好,但是 R9 是一个 qword 寄存器,所以你应该加载带有符号扩展的值:
movsx r13, dword [r9 + r12 * 4]
或者,您可以将数组元素定义为 qwords,然后编写:
mov r13, [r9 + r12 * 8]
syscall
你有一个冗余的 SYSCALL 指令。将被删除。
处理负输入的代码如果写成这样会更好看:
mov rsi, blank
test r13, r13 ; determine number is negative or positive
jns IsPos ; if it is positive we print BLANK
mov rsi, minus ; else we print MINUS
neg r13 ; convert the negative number to positive number
IsPos:
mov rax, 1
mov rdi, 1
mov rdx, 1
syscall
L1:
mov rbx, r14 ; divisor idiv rbx ; after the div operation rbx store division
首先将除数从 R14 移动到 RBX 没有任何好处。你可以简单地写:
idiv r14
.
; print digit add rsp , 8
在print digit中,存在
add rsp, 8
操作以从堆栈中删除push r10
值。显然,您只能在推送执行后执行此操作。
; print digit
add r10, 48
mov rax, 1
mov rdi, 1
push r10 ; (1)
mov rsi, rsp
mov rdx, 1
syscall
add rsp, 8 ; (1)
; 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
在mod操作中,
xor rdx, rdx
破坏了执行cqo
的努力,这在使用idiv
之前是正常的。您 can 使用 xor rdx, rdx
但与 div
(无符号除法)结合使用。
; 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)
在将除数减少 10 倍的部分中,您引入了将 RDX 设置为 1 的错误,在使用
div
之前应该将其归零。此外,除法的商在 RAX 中,因此将其移至 R14。
代码不是最优的。使用收缩除数的数字转换比使用固定除数 10 并向后存储更昂贵。
global _start
section .text
_start:
mov r9, number ; address 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, [divisor] ; get initial DIVISOR
mov r13, [r9 + r12 * 8] ; get array number for using array address. We use 8*k because we take k. index of array
mov rsi, blank
test r13, r13 ; determine number is negative or positive
jns IsPos ; if it is positive we print BLANK
mov rsi, minus ; else we print MINUS
neg r13 ; convert the negative number to positive number
IsPos:
mov rax, 1
mov rdi, 1
mov rdx, 1
syscall
L1:
; division operation digit = (number/digits)
mov rax, r13 ; dividend
cqo
idiv r14
mov r10, rax ; result is equal digit (r10)
; print digit
add r10, 48
mov rax, 1
mov rdi, 1
push r10 ; (1)
mov rsi, rsp
mov rdx, 1
syscall
add rsp, 8 ; (1)
; mod operation number = number % digits
mov rax, r13 ; dividend
cqo
idiv r14
mov r13, rdx ; rdx store remainder and remainder equal number
; division operation digits = (digits/10)
mov rax, r14 ; dividend
xor edx, edx ; Equivalent and better than `mov rdx, 0`
mov rbx, 10 ; divisor
div rbx
mov r14, rax
inc r15 ; increment the loop register
cmp r15, 9 ; compare loop register with 9 so loop work 8 times
jb 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
jb L3 ; if k less than numberCount, goto L3 that is beginning 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 dq 0
k dq 0
divisor dq 100000000
number dq 321762410, 9, 2943018, 0, 19372039, 18, -76241, -208424