%include "asm_io.inc"
;
; initialized data is put in the .data segment
;
segment .data
array: dd 180,32,455,499,388,480,239,346,257,84
fmt: dd ",%d",0
; uninitialized data is put in the .bss segment
;
segment .bss
resd 10
;
; code is put in the .text segment
;
segment .text
extern printf
global asm_main
asm_main:
enter 0,0 ; setup routine
pusha
; The following is just example of how to print an array
push dword 10
push dword array
call print_array
add esp,8 ; clean up stack
; don't delete anything following this comment
popa
mov eax, 0 ; return back to C
leave
ret
segment .data
ListFormat db ",%u", 0
segment .text
global print_array
print_array:
enter 0,0
push esi
push ebx
xor esi, esi ; esi = 0
mov ecx, [ebp+12] ; ecx = n
mov ebx, [ebp+8]
xor edx, edx
mov dl, [ebx + esi] ; ebx = address of array
mov eax,edx
call print_int
dec ecx
inc esi
print_loop:
xor edx,edx
mov dl,[ebx + esi]
push ecx ; printf might change ecx!
push edx ; push array value
push dword ListFormat
call printf
add esp, 8 ; remove parameters (leave ecx!)
inc esi
pop ecx
loop print_loop
call print_nl
pop ebx
pop esi
leave
ret所以当我想打印180,32,455,499,388,480,239,346,257,84时,这个代码会打印出180,0,0,0,32,0,0,0,199,1。我认为这是因为它是为打印字节字而设计的。我正在尝试以双字打印,我猜print_array中的某些内容需要更改。我尝试了mov dl,ebx+esi*4,但它仍然没有打印出我想要打印的数组。或者,是否需要将其他内容更改为打印双字数组?
发布于 2020-12-17 23:38:29
您可以将mov dl, [ebx+esi]指令更改为mov edx, [ebx+esi*4],但这只是一半的乐趣!
1为什么不尝试创建一个循环来处理列表中不需要逗号前缀的第一个值的特殊情况?不再使用print_int。
2也不使用LOOP指令。太慢了!配对cmp jb (可以进行宏观融合)要好得多。
3和通过简单地通过ESP相对寻址来寻址参数来替换prolog enter 0,0和epilog leave代码非常简单。
4总是考虑特殊情况!如果数组碰巧是空的怎么办?
print_array:
push ebx
push esi
mov ebx, [esp+12] ; Begin array
mov esi, [esp+16] ; n
test esi, esi
jz done
lea esi, [ebx+esi*4] ; End array
mov edx, ListFormat+1 ; "%u"
more: mov eax, [ebx] ; Array dword value
push eax
push edx ; "%u" first time, ",%u" others
call printf
add esp, 8
add ebx, 4 ; To next dword in the array
mov edx, ListFormat ; ",%u"
cmp ebx, esi ; Current address < Last address ?
jb more ; Yes
call print_nl
done: pop esi
pop ebx
ret在适当的条件下,将ESP固定在这个循环中是值得做的。请参阅此答案下面Peter Cordes的评论。
接下来是这段代码的一个版本,它将ESP固定在循环中:
print_array:
push ebx
push esi
mov ebx, [esp+12] ; Begin array
mov esi, [esp+16] ; n
test esi, esi
jz done
sub esp, 8 ; Space for the printf args
lea esi, [ebx+esi*4] ; End array
mov edx, ListFormat+1 ; "%u"
more: mov eax, [ebx] ; Array dword value
mov [esp+4], eax
mov [esp], edx ; "%u" first time, ",%u" others
call printf
add ebx, 4 ; To next dword in the array
mov edx, ListFormat ; ",%u"
cmp ebx, esi ; Current address < Last address ?
jb more ; Yes
call print_nl
add esp, 8
done: pop esi
pop ebx
rethttps://stackoverflow.com/questions/65334735
复制相似问题