Arrays 迭代汇编中的数组以求解一般方程
我正在使用NASM学习汇编语言,遇到了一个似乎无法解决的编程问题。该计划的目标是求解此方程: 对于那些看不到照片的人,方程式表示,对于长度为n的两个数组,数组a和数组b,找到:对于i=0到n-1,((ai+3)-(bi-4)) 我只需要使用三个通用寄存器,我已经找到了一个我认为可能有效的代码示例,但我在第16行和第19行中不断遇到逗号和操作数错误。我知道,为了遍历数组,需要将指针移动到每个索引,但由于两个数组的值不同(数组1是dw,数组2是db),我不确定如何解释这一点。我对汇编还是一个新手,任何帮助或指点都将不胜感激。 下面是我当前代码的图片:Arrays 迭代汇编中的数组以求解一般方程,arrays,assembly,x86-64,nasm,Arrays,Assembly,X86 64,Nasm,我正在使用NASM学习汇编语言,遇到了一个似乎无法解决的编程问题。该计划的目标是求解此方程: 对于那些看不到照片的人,方程式表示,对于长度为n的两个数组,数组a和数组b,找到:对于i=0到n-1,((ai+3)-(bi-4)) 我只需要使用三个通用寄存器,我已经找到了一个我认为可能有效的代码示例,但我在第16行和第19行中不断遇到逗号和操作数错误。我知道,为了遍历数组,需要将指针移动到每个索引,但由于两个数组的值不同(数组1是dw,数组2是db),我不确定如何解释这一点。我对汇编还是一个新手,任
您使用的是16位和8位数据,但使用的是64位寄存器。一般来说,处理器需要相同的数据大小,但不包括任何单个指令的操作数
cmp-rax,[n]
具有不同的数据大小,这是不允许的:rax
是64位寄存器,[n]
是16位数据项。因此,我们可以将其更改为cmp-ax,[n]
,现在所有内容都是16位
add rbx,a[rax*4]
也混合了不同大小的操作数(不允许)。rbx
是64位,a[]
是16位。您可以将寄存器更改为bx
,这是允许的。但我们也要注意,*4
太多了,应该是*2
,因为dw
是16位数据(2字节),而不是32位(4字节)。由于您正在清除rbx
,因此不需要add
,只需mov
添加rdx,字节b[rax]
也混合了不同的大小。rax
是64位宽,而b[]
的宽度为8位。请使用dl
而不是rdx
。没有什么可添加的,因此您应该使用mov
而不是add
。既然dl
中有一个值,并且您以前清除了rdx
,您可以切换到使用dx
(从dl
)这将具有16位的b[i]值
sub-rbx,[rdx]
有一个错误的尊重。这里您只想sub-bx,dx
您没有使用标签
loop\u start
,因此没有循环。(在循环末尾添加一个向后分支。)您使用的是16位和8位数据,而是64位寄存器。一般来说,处理器需要相同的数据大小,尽管任何一条指令的操作数不同
cmp-rax,[n]
具有不同的数据大小,这是不允许的:rax
是64位寄存器,[n]
是16位数据项。因此,我们可以将其更改为cmp-ax,[n]
,现在所有内容都是16位
add rbx,a[rax*4]
也混合了不同大小的操作数(不允许)。rbx
是64位,a[]
是16位。您可以将寄存器更改为bx
,这是允许的。但我们也要注意,*4
太多了,应该是*2
,因为dw
是16位数据(2字节),而不是32位(4字节)。由于您正在清除rbx
,因此不需要add
,只需mov
添加rdx,字节b[rax]
也混合了不同的大小。rax
是64位宽,而b[]
的宽度为8位。请使用dl
而不是rdx
。没有什么可添加的,因此您应该使用mov
而不是add
。既然dl
中有一个值,并且您以前清除了rdx
,您可以切换到使用dx
(从dl
)这将具有16位的b[i]值
sub-rbx,[rdx]
有一个错误的尊重。这里您只想sub-bx,dx
您没有使用标签loop\u start
,因此没有循环。(在循环末尾添加一个向后分支。)
…但由于两个数组的值不同(数组1是dw
,数组2是db
),我不确定如何解释这一点
解释了为什么“一直遇到逗号和操作数错误”。虽然可以恢复使用较小的寄存器(添加操作数大小前缀),但我的回答采用了不同的方法
指令集有movzx
(零扩展移动)和movsx
(符号扩展移动)指令来处理这些不同的大小。请参见下面的使用方法
我也应用了一些更改
- 不要错过简化计算的机会:
相当于((a[i]+3)-(b[i]-4))
(a[i]-b[i]+7)
- 这些数组都不是空的,因此您可以将循环条件放在其主体下方
- 如果方便的话,可以从末尾开始处理数组。求和操作不介意
-2
和-1
,以补偿循环控件在{2,1,0}时采用值{3,2,1}的事实这不会在指令中引入额外的位移分量,因为提到a和b数组实际上已经是位移了
虽然标记为x86-64,但您可以使用32位寄存器编写整个程序,而不需要REX前缀。结果相同
…但由于两个数组的值不同(数组1是dw
,数组2是db
),我不确定如何解释这一点
解释为什么您“不断遇到逗号和操作数错误”
segment .data
a dw 12, 14, 16 ; array of three values
b db 2, 4, 5 ; array of three values
n dw 3 ; length of both arrays
result dq 0 ; memory to result
segment .text
global main
main:
mov rax, 0
mov rbx, 0
mov rdx, 0
loop_start:
cmp rax, [n]
jge loop_end
add rbx, a[rax*4] ; adding element of a at current index to rbx
add rbx, 3 ; adding 3 to current index value of array a in rbx
add rdx, BYTE b[rax]
sub rdx, 4
sub rbx, [rdx]
add [result], rbx
xor rbx, rbx
xor rdx, rdx
add rax, 1
loop_end:
ret
segment .data
a dw 12, 14, 16 ; array of three values
b db 2, 4, 5 ; array of three values
n dw 3 ; length of both arrays
result dq 0 ; memory to result
segment .text
global main
main:
movzx rcx, word [n]
loop_start:
movzx rax, word [a + rcx * 2 - 2]
movzx rbx, byte [b + rcx - 1]
lea rax, [rax + rbx + 7]
add [result], rax
dec rcx
jnz loop_start
ret
segment .data
a dw 12, 14, 16 ; array of three values
b db 2, 4, 5 ; array of three values
n dw 3 ; length of both arrays
result dq 0 ; memory to result
segment .text
global main
main:
movzx ecx, word [n]
loop_start:
movzx eax, word [a + ecx * 2 - 2]
movzx ebx, byte [b + ecx - 1]
lea eax, [eax + ebx + 7]
add [result], eax
dec ecx
jnz loop_start
ret