我正在尝试编写一个使用NASM实现矩阵的程序。作为初学者,我尝试在NASM中重写以下C代码。 C代码:
for(i = 0 ; i< 3; i++){
for(j = 0 ;j < 3; j++)
a[i][j] = 0 ;
}
我的以下NASM代码实现是:
section .data
msg db "%d"
four dd 4
spce db " ",0
nl db 10
section .bss
arr1 resd 4
arr2 resd 4
section .text
global main
extern printf
main:
nop
xor ecx,ecx
xor eax,eax
xor ebx,ebx
lp1: ;to implement "for(r = 0 ; r < 4; r++)"
mov ebx, arr1
mov eax,ecx
mul dword[four]
add ebx,eax
cmp ecx,4
jl entryOflp2
jmp done
entryOflp2: ; to implement for(c = 0 ; c < 4; c++)
push ebx
push ecx
xor ebx,ebx
xor edx,edx
lp2:
mov ebx, arr2
mov eax,edx
mul dword[four]
add ebx,eax
mov dword[ebx],0 ; to initial a[r][c]=0
inc edx
cmp edx,4
jl lp2
endOflp2:
pop ecx
pop ebx
inc ecx
cmp ecx,4
jl lp1
done:
ret
但是我发现我的程序在一个无限循环中失败了,最值得注意的是edx的值没有递增。作为初学者,我很少怀疑我是否应该以这种方式实现矩阵。
我正在寻找导师的建议。我使用的是UBUNTU 11.04操作系统。
遵循导师Brendon的建议,我按照以下方式更改了上述代码;仍然没有得到我想要的输出:
section .bss
arr1 resd 9
section .text
global main
extern printf
main:
nop
xor ecx,ecx
xor eax,eax
xor ebx,ebx
mov ebx, arr1
forI:
xor esi,esi
cmp ecx,3
jl forJ
jmp print
forJ:
cmp esi,3
jl initialization
inc ecx
jmp forI
initialization: ; it will give base address+4(number
;of colums*rowIndex+columIndex).
;ecx=row index,esi=column index; I am using Row major represntation
mov eax,ecx
mul dword[three]
add eax,esi
mul dword[four]
add ebx,eax
mov dword[ebx],0 ;set a[i][j]=0
inc esi
jmp forJ
print:
xor ecx,ecx
xor eax,eax
xor ebx,ebx
mov ebx, arr1
forI_2:
xor esi,esi
cmp ecx,3
jl forJ_2
jmp done
forJ_2:
cmp esi,3
jl print_task
pusha
push nl
call printf
add esp,4
popa
inc ecx
jmp forI_2
print_task:
mov eax,ecx
mul dword[three]
add eax,esi
mul dword[four]
add ebx,eax
pusha
push dword[ebx]
push msg
call printf
add esp,8
popa
pusha
push spce
call printf
add esp,4
popa
inc esi
jmp forJ_2
done:
nop
我的预期输出将是
0 0 0
0 0 0
0 0 0
但输出来的是 0123012301230 0 0 分段错误
我仍然在寻找你的建议。 谢谢。
答案 0 :(得分:1)
您没有展示如何在C中定义“数组数组”;但是从使用a[r][c]
开始,我假设你正在做类似的事情:
int a[4][4];
在内存中,这将是一个包含16个整数的数组(或4个4个整数组)。在您的NASM代码中,您可以执行以下操作:
section .bss
arr1 resd 4
arr2 resd 4
这不是16个整数的数组。它是4个4个整数的独立数组。它应该是:
section .bss
arr resd 4*4
MUL
指令将EAX中的32位值乘以另一个32位值(在您的情况下为4),并将64位结果存储在EDX:EAX中。您正在使用EDX来控制内循环,MUL
正在破坏EDX。这是你的无限循环的原因(基本上,它正在循环,直到0 * 4的结果不小于0x0000000400000000)。
另请注意,乘法是不必要的。将“sizeof(int)”添加到指针更容易。例如(使用C作为伪代码)for(void *c = a; c < (void *)a + 4 * sizeof(int); c += sizeof(int)) { ... }
。在汇编中,这可能看起来像:
mov edx,arr
.next:
...
add edx,4
cmp edx,arr+4*4
jb .next
同样适用于外循环。例如(合并):
mov ecx,arr
.next1:
mov edx,ecx
lea edi,[ecx+4*4]
.next2:
...
add edx,4
cmp edx,edi
jb .next2
add ecx,4*4
cmp ecx,arr+4*4*4
jb .next1
当然也不需要嵌套循环,因为你对数组数组中的每个整数做了同样的事情。你可以这样做:
mov ecx,arr
.next1:
mov dword [ecx],0
add ecx,4
cmp ecx,arr+4*4*4
jb .next1
这可以再次简化 - 它可能只是C中的memset()
;或者像汇编这样的东西:
mov edi,arr ;es:edi = address of array of arrays
mov ecx,4*4 ;ecx = size of array of arrays (16 integers)
xor eax,eax ;eax = value to fill the integers with
rep stosd ;Fill the array