본문 바로가기

애니리뷰

어셈블리] 문자열을 입력한 다음 spacebar 기준으로 거꾸로 출력하기

.data 
str1 BYTE "Input: ", 0
str2 BYTE "Output: ", 0
str3 BYTE 60 DUP(?)
str4 BYTE 60 DUP(?)
var1 BYTE 0
;-------------------------코드-----------------------------
.code 
main PROC
L0:
mov edx, OFFSET str1
call WriteString
mov ecx, LENGTHOF str3
mov edx, OFFSET str3
call ReadString
cmp eax, 40
ja L0
mov esi, 0
cmp str3[esi], 0
je L5
mov ecx, LENGTHOF str3
mov edi, 0
L1:
movzx eax, str3[esi]
cmp str3[esi], 0
je L4
cmp str3[esi], 32
je L2
push eax
inc esi
inc var1
loop L1

L6:
mov edx, OFFSET str2
call WriteString
mov edx, OFFSET str4
call WriteString
call crlf
jmp fin
finale:
loop L0

L4:
mov ebx, ecx
movzx ecx, var1
L7:
pop eax
mov str4[edi], al
inc edi
loop L7
pop ecx
inc esi
mov ecx, ebx
mov var1, 0
jmp L6

L2:
mov ebx, ecx
movzx ecx, var1
L3:
pop eax
mov str4[edi], al
inc edi
loop L3
mov str4[edi], 32
inc edi
inc esi
mov ecx, ebx
mov var1, 0
jmp L1

fin:
mov edi, 0
mov ecx, LENGTHOF str4

final:
mov str4[edi], 32
inc edi
loop final

finalfinal:
mov var1, 0
jmp finale

L5:


main ENDP
END main

 

---------------------------------------------

루프가 생각보다 중구난방하다.

우선 L0은 가장 기본적인 루프다.

cmp str3[esi], 0 
je L5 

에서, 입력받은 STRING이 공백일 경우, L5로 점프해서 L0을 탈출한다.

즉, 입력된 문자가 하나라도 있다면, 무조건 L0을 반복한다.

 

L1: 
movzx eax, str3[esi] 
cmp str3[esi], 0 
je L4 
cmp str3[esi], 32 
je L2 
push eax 
inc esi 
inc var1 
loop L1 

 

루프1은 STR을 지속적으로 ESI를 1 추가시켜가며, 동시에 VAR1을 증가시켜가며 SPACEBAR가 오기까지의 CHAR개수를 센다.

만일 엔터가 온다면 L4로, 스페이스바가 온다면 L2로 점프한다.

 

L4: 
mov ebx, ecx 
movzx ecx, var1 
L7: 
pop eax 
mov str4[edi], al 
inc edi 
loop L7 
pop ecx 
inc esi 
mov ecx, ebx 
mov var1, 0 
jmp L6 

L2: 
mov ebx, ecx 
movzx ecx, var1 
L3: 
pop eax 
mov str4[edi], al 
inc edi 
loop L3 
mov str4[edi], 32 
inc edi 
inc esi 
mov ecx, ebx 
mov var1, 0 
jmp L1 

 

L2와 L4은 기본적으로 같은 역할을 수행한다. 위에서 PUSH한(push eax) EAX를 반대로 POP해가며, 반대로 된 문자열을 저장할 STR4에 추가시켜간다. 만일 VAR1, 즉 저장된 만큼의 문자열을 전부 반대로 했을 때, L4는 문자열이 끝났단 의미이므로 L6으로 점프하며, L2는 아직 문자열이 남아있단 뜻이므로 다시 L1으로 점프한다.

 

 

L6: 
mov edx, OFFSET str2 
call WriteString 
mov edx, OFFSET str4 
call WriteString 
call crlf 
jmp fin 
finale: 
loop L0 

 

그러면 STR4를 WRITESTRING하고 끝.

 

fin: 
mov edi, 0 
mov ecx, LENGTHOF str4 

final: 
mov str4[edi], 32 
inc edi 
loop final 

finalfinal: 
mov var1, 0 
jmp finale 

 

이건 별거 없다. 그냥 STR4를 전부 스페이스바로 초기화시키는 것이다.

어차피 CALL CRLF를 통해 다음 문장을 호출할 것이므로 의미는 없다.