2016-10-20 3 views
0

x86 아키텍처를 사용하여 어셈블리를 배우려고합니다. add, sub, mul, imul, div, idiv와 같은 기본적인 계산을 할 수 있습니다. 그러나 결과를 인쇄하려고하면 문자열에 여러 공백이 있습니다. 이러한 여분의 공간을 제거 할 수있는 방법이 있습니까? 현재 문자열을 반복하고 비 공백 문자를 두 번째 문자열로 보내서 제거하려고합니다. 이렇게하는 것이면 내 코드가 작동하지 않는 이유는 무엇입니까? 나는 어딘가 교환 (xchg)에 대해 읽었지 만 그것을 사용하는 방법을 완전히 모르겠습니다. 이것이 더 효율적인 방법일까요?어셈블리 x86 Win32

   dtoa  product, eax  ; convert to ASCII characters 
       dtoa  xStart, x 
       dtoa  yContinue, y 
       lea  edi, product 
       mov  ecx, 20h   ; mov hex value of space into ecx 

forStart:  cmp  [edi], ecx  ; compare edi to space 
       jne  addToString 
       add  edi, 4   ; get address of next array element 
       cmp  [edi], 00h  ; cmp value of edi to null 
       je  printResult 
       jmp  forStart   ; loop through for next element 

addToString: mov  ecx, [edi]  ; mov value of edi into ecx 
       add  edi, 4   ; get address of next array element 
       cmp  [edi], 00h  ; cmp value of edi to null 
       je  printResult 
       jmp  forStart   ; loop through for next element 

printResult: output resultLbl, xStart ; output result 

답변

-1

이것은 매우 불완전합니다. dtoa은 x86 명령어가 아니므로, 무엇을하는지 (아마도 10 진수에서 10 진수로 변환 루틴으로 변환하기는 어렵지만, 정확히 무엇이 생성되고 어떻게 작동하는지 알기가 어렵습니다. 소스 또는 적절한 문서가 없으면 수수께끼입니다).

product 선언이 누락되었거나 문서화되지 않았습니다.

그리고 "문자열"이 무엇인지 정의하지 않아도됩니다.

   mov  ecx, 20h   ; mov hex value of space into ecx 
forStart:  cmp  [edi], ecx  ; compare edi to space 
       jne  addToString 

cmp [edi],ecx' '으로 DWORD 값을 비교합니다 (BTW, 당신이 mov ecx,' '로 첫 번째를 쓸 수 있습니다), 그래서 당신을 : 다음 코드에서 당신이 때문에

사람들의 모든

은 중요하다 문자열의 UTF-32 인코딩을 사용합니까? 클래식 ASCII 인코딩을 사용하는 경우 BYTE 만 비교 ( cmp [edi],cl)하고 1 ( add edi,1)까지만 진행해야합니다.

cmp [edi], 00h -> 어떤 크기의 값을 비교하지 않고 NASM에 cmp [edi], BYTE 00h과 같은 크기 지정자를 사용하십시오.

addToString에서 4 바이트의 문자열을 가져 오지만 거기에 "추가"하는 부분이 없으므로 아무 것도하지 않습니다. 다시 4 바이트 요소를 사용하면 UTF-32 인코딩에서 유효하지만, 어떻게 든 ASCII 영숫자 문자열을 사용하고있는 것으로 의심됩니다. 대신 바이트로 작업해야합니다.

명령어로 명령어를 실행하고 레지스터 값이 변경되는 방식을 고려하면 디버거에서 대부분 알아낼 수 있으며 흥미로운 주소에서 메모리 내용을 볼 수 있습니다 (edi' ', 기타). 그리고 지침 참조 가이드에 맞춰 각 지침이 정확히 어떻게 작동하는지 이해하도록하십시오.

그래서이 질문은 노력 (디버깅) + 디버깅을 묻습니다. 당신이 그것을 쓴

귀하의 코드 즉, 정확히 작동 하는가 :

그리고 마지막 질문 (들) 자체에 대한

. 비 - 공백 문자를 두 번째 문자열로 보내기 "라는 원래의 의도와는 완전히 관련이 없기 때문에 코드는 그 코드에 가까이 있지 않습니다.

왜 당신이 관련없는 코드를 썼는지 ... 말하기 어렵다. 아마도 원래의 의도를 더 간단한 하위 작업 (영어로 된 설명)으로 나눠서 시도해야하며, 간단한 하위 단계별 지침을 제공하므로 디버그 중에 CPU에서 발생한 일을 원래 의도와 비교할 수 있습니다.

xchg은 두 값을 서로 바꿉니다.문자열을 메모리에 저장하는 방법을 이해하고 다른 값 (사용자의 의도에 따라 다름)과 교환하려는 값을 이해하면 문자열 조작에도 이러한 지시를 사용할 수 있습니다.

더 효율적인 방법이 있습니까?

말씀하기가 어렵습니다. 당신이 달성하기를 원하는 것이 확실하지 않습니다. "현재 출력 : ____30"(_가 공백 인 경우), "원하는 출력 : 30"이면 문자열을 수정할 필요가 없습니다. 초기 공백 문자를 계산하고 "출력"서브 루틴을 지정해야합니다. xStart + <space_count> 주소이므로 공백이 포함 된 바이트가 발생하지 않습니다. 아니면 dtoa에 대한 설정이 있거나 라이브러리에 C printf처럼 작동하는 몇 가지 다른 기능이 있습니다. 정확한 형식을 쉽게 지정할 수 있습니다.


편집 : "말할 하드"강조 :

그리고 당신은 코드를 유지 의견은 종종 쓸모없는, 또는 잘못입니다.

addToString: mov  ecx, [edi]  ; mov value of edi into ecx 

첫째, ecxedi 값으로 이동하지 않지만, 메모리 내용의 차이 값은 치명적이다 edi, 어드레스에 의해 지시.

둘째로, 당신은 명백한 진술, 그 명령이하는 것입니다. 당신은 오히려 즉, 당신의 "인간의 의도"코멘트에 보관해야합니다 : 당신의 인간의 의도가 꺼져가는 곳

addToString: mov  ecx, [edi]  ; reading 4 ASCII letters of string into ecx 

당신이 그렇게한다면, 지적 쉬울 것, 지침의 구현과 비교하고, 당신에게 당신의 마음 수준 실수를 지적하십시오.

마찬가지로, 대신에 작업 코드를 작성하는 것이 가능하지만, 왜 그렇게 다른지와 작동 원리를 이해할 수 있는지 여부 ... 그렇다면 이해하기 위해 많은 노력이 필요합니다.) 진정으로 당신을 도울 것입니다. 그리고 문제의 노력이 부족하다는 것을 보여줍니다 - 실제 사례를 제공 할 필요가 없습니다.