0

您好,我是组装新手,我正在努力让一个由两部分组成的程序工作。我正在为这个 x86 程序集使用 Visual Studio。

第 I 部分)我的第一个目标是数到 13,并在途中添加每个值。例如,0+1+2+3...+13=91。我想总共存储该总数。

第 2 部分)其次,我想用 2 的幂从 2^0 数到 2^6。例如,0、1、2、4、8、32、64。我想*我正在这样做,但我并没有随时存储每个值。我想将这些存储在连续的内存位置。

到目前为止,我有这个,

.586
.MODEL FLAT

.STACK 4096

.DATA
num1 BYTE 13          ;Initialize number to count to
totall BYTE 0         ;Total of all counted numbers
temp BYTE 0           ;Temp for loop adding

shiftme BYTE 1        ;Start of counting 2^0 so I can reach 2^6

.CODE
main PROC
;code here

increment:            ;Increment label
inc temp              ;Increment temp by 1
mov eax, temp
add totall, eax       ;Add temp+totall and store in totall
cmp eax, num1         ;Compare for jump
jne increment         ;Jump if not equal

;this part should store each value 1,2,4,8,32.. in consecutive memory locat
shiftallthethings:    ;Shift label
shl shiftme, 1        ;Shifting bits to the left one
cmp shiftme, 64       ;Comparing for the jump
jne shiftallthethings ;Jump if not equal to

ret
main ENDP
END

帮助我理解的问题。

  • 如何将值存储在连续的内存位置?
  • 我是否正确使用了跳转和标签指令?
  • 我是否需要使用像 eax 这样的特定寄存器来执行这些问题?为什么?

非常感谢任何帮助,谢谢。

4

1 回答 1

2

首先,回答您的问题:

如何将值存储在连续的内存位置?

在 MASM32 中,您可以直接执行mov类似操作mov sum_addr, eax(只要数据类型具有相同的大小),也可以传递数据指针。在我编写的示例中,指向total函数的指针被传递。然后该函数将一个值写入该指针指向的内存(即 的内容total)。不太清楚你所说的连续内存位置是什么意思。如果您的意思是指针算术,我也可以向您展示一个示例。

我是否正确使用了跳转和标签指令?

是的,这似乎很好。我使用的另一种方法是匿名标签。当标签是微不足道的并且相当接近时,这是合适的。这是个人喜好。如果您觉得标签名称更合适,也可以随意使用。

我是否需要使用像 eax 这样的特定寄存器来执行这些问题?为什么?

MASM32 遵循 Win32 (stdcall) 的调用约定,因此您也可以这样做。在寄存器保存方面,这意味着所有函数都应该保存除eax,ecx并且edx被视为可回收的寄存器。如果需要超过 4 个字节,则返回值存储在eaxoreax中。edx


就您编写的代码而言,您遇到了一些问题,例如尝试将不同大小的数据类型相互移动。例如,如果将 a 移动byte到 adword中,则必须先将其扩展为相同的大小。

mov eax, temp

这不会编译,因为temp它只有 1 个字节长,而eax4 个字节。你可以这样做:

movzx eax, temp

这在移动之前零扩展temp。这是我整理的一些代码,可能会教给您一些东西。它使用宏(不确定您是否想学习这些),但在其他方面演示了惯用的 MASM32 参数传递和返回值。

include \masm32\include\masm32rt.inc

.DATA

total DWORD 0         ;Total of all counted numbers

.CODE

; takes in address of total and writes the value there
sum PROC sum_addr:DWORD

xor eax, eax
xor ecx, ecx

  @@:
inc ecx
add eax, ecx
cmp ecx, 13
jnz @b

mov edx, sum_addr
mov dword ptr ds:[edx], eax
print ustr$(eax), 13, 10

mov edx, sum_addr
mov eax, dword ptr ds:[edx]
ret

sum ENDP

start:

push offset total          ; pass address of total
call sum
print ustr$(eax), 13, 10   ; demonstrating how to use return values

print ustr$(total), 13, 10 ; testing result got stored properly
ret

end start
END

代码未优化,但应该易于理解。请注意我是如何尽可能多地使用寄存器的(如果我们有足够的寄存器,这比不断处理内存更有效)。

于 2012-03-26T20:54:27.860 回答