2012-03-26 3 views
0

안녕하세요 저는 새 어셈블리입니다. 두 부분으로 구성된 프로그램을 사용하는 데 어려움을 겪고 있습니다. 이 x86 어셈블리에 Visual Studio를 사용하고 있습니다.x86 어셈블리 초보자 : 기본 추가 및 저장 문제

파트 I) 첫 번째 목표는 최대 13 개까지 계산하여 거기에서 각 값을 추가하는 것입니다. Ex, 0 + 1 + 2 + 3 ... + 13 = 91이다. 총계를 토탈에 저장하고 싶습니다.

파트 2) 두 번째로, 나는 2^0에서 2^6까지의 2의 제곱으로 계산하고 싶습니다. 예, 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와 같은 특정 레지스터를 사용해야합니까? 왜?

어떤 도움을 주셔서 감사합니다. 질문에 대한

대답 모든
+1

연속적인 메모리 위치의 저장 값은 무엇을 의미합니까? 우리가 해결할 구체적인 문제를 제기 할 수 있습니까? 또한 MASM32로 태그가 지정되었습니다. –

+0

@MikeKwan 우리가 그 점을 무시하면 매번 label에 점프하는 동안 매번 shiftme를 어떻게 저장합니까? 또한이 코드는 게시 한 문제를 해결하는 데 의미가 있습니까? – KRB

+0

'add totall, temp','cmp temp, num1'은'add '와'cmp'가 양쪽 피연산자를 메모리에 가질 수 없기 때문에 잘못되었습니다. 유효한 조합 : 레지스터 + 메모리 또는 메모리 + 레지스터, 레지스터 + 즉치 상수, 메모리 + 상수. 여기에 등록부를 사용해야합니다. –

답변

2

첫째, :

어떻게 연속 메모리 위치에 하나의 값을 저장합니까?

MASM32, 당신은 직접 할 수있는 movmov sum_addr, eax 같은 (한 데이터 유형이 같은 크기로)하거나 데이터 포인터 주위에 전달할 수 있습니다. 필자가 작성한 예제에서는 total에 대한 포인터가 함수로 전달됩니다. 함수는 그 포인터가 가리키는 메모리에 값을 씁니다 (즉 내용은 total입니다). 연속적인 메모리 위치가 무엇을 의미하는지 확신 할 수 없습니다. 당신이 포인터 연산을 의미한다면, 나는 그것의 예를 보여 줄 수있다.

점프 및 라벨 지침을 올바르게 사용하고 있습니까?

네, 괜찮습니다. 제가 사용하는 대안은 익명의 레이블입니다. 라벨이 사소하고 가까이에있을 때 적합합니다. 개인적인 취향입니다. 라벨 이름이 더 적절하다고 생각되면 자유롭게 사용하십시오.

이러한 문제를 해결하려면 eax와 같은 특정 레지스터를 사용해야합니까? 왜?

MASM32는 Win32 (stdcall)의 호출 규칙을 따르므로이 작업을 수행하는 것이 좋습니다. 레지스터 보존의 관점에서 보면, 모든 함수는 eax, ecxedx을 제외하고는 레지스터를 유지할 것으로 예상되며, 이는 휴지통으로 간주됩니다. 반환 값은 4 바이트가 넘는 경우 eax 또는 eaxedx에 저장됩니다.


작성한 코드의 측면에서 서로 다른 크기의 데이터 유형을 서로 이동하려고 시도하는 것과 같은 몇 가지 문제점이 있습니다. 예를 들어 bytedword으로 옮기는 경우 먼저 크기를 늘려야합니다. temp 단지 1 바이트 길어서 eax 4 바이트 인 반면, 컴파일되지

mov eax, temp 

. 대신 할 수있는 :

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 

코드는 최적화되지 않았지만 쉽게 이해할 수 있어야합니다. 레지스터를 가능한 한 많이 사용하려고 시도했음을 주목하십시오 (레지스터가 충분하면 메모리를 계속 처리하는 것보다 효율적입니다).