2016-09-09 1 views
0

디버그 유틸리티를 사용하여 DOSBox를 실행하여 어셈블리 코드를 작성합니다. 나는 단지 문자열을 읽는 방법을 알아 내려고 노력하고있다. 나는 이것을 지금까지 가지고있다.DOSBox 디버그 어셈블리

-n test.com 
-a 
072A:0100 db 15 
072A:0101 db 16 
072A:0102 mov dx, 100 
072A:0105 mov ah, 0A 
072A:0107 int 21 
072A:0109 int 20 

-rcx 15 
-w 
-q 

그래서 버퍼에서 15 자 이하의 문자열을 읽을 수 있습니다. 문자열을 읽을 때 어디에 배치됩니까? 끈을 다시 인쇄 해보고 싶습니다.

+0

당신은 15 바이트를 예약하지 않았습니다. 당신은 15를 포함하는 위치 100에 바이트를 예약했습니다. 16을 포함하는 101의 바이트를 예약했습니다. 당신이'DUP '지시어. –

+0

질문은 약간 불분명하고 너무 광범위합니다. 당신은 해골을 조금 더 생각해야하고 질문을 어느 정도 좁혀 야합니다. –

+2

@DavidHoelzer : DOS 디버그가 DUP와 같은 것을 지원하지 않는다고 생각하지 마십시오. 레이블은 지원되지 않습니다. –

답변

3

샘플 코드에 2 개의 문제점이 있습니다.

DOS가이 주소에서 실행을 시작하기 때문에 원시 데이터를 오프셋 100에 배치하지 않으려합니다. 이 때문에 오프셋 102에서 시작하는 코드는 "mov dx, 100"명령에서 BA 바이트를 훔치는 "ADC AX, BA16"명령으로 어셈블되고 나머지 명령은 잘못 해석 될 것이기 때문에 제대로 실행되지 않습니다 .

문제 # 1이 없다면 두 번째 문제는 입력 문자가 오프셋 102에서 시작하는 코드를 덮어 쓰게된다는 것입니다 (버퍼의 처음 2 바이트가 예약되어 있으므로). 코드를 실행할 수 있다면, 이것은 아마도 당신이 원하는 것이 아닙니다. ;)

오프셋 (offset) 100의 데이터를 .COM 프로그램의 진입 점으로 정의하고 싶지는 않습니다. 이것을 처리하는 간단한 방법은 코드 뒤에 데이터를 정의하는 것입니다. 라벨을 사용하지 않고 직접 메모리 위치를 지정해야하는 곳에서 디버그와 같은 것을 사용할 때는 어셈블 된 피연산자의 크기를 고려해야합니다.

한 가지 방법은 주소 100에서 시작하여 코드를 조합하고 문자열 및 버퍼 주소에 자리 표시자를 사용하는 것입니다. 그런 다음 데이터를 정의한 후에 지침을 수정하십시오. 여기

는 수정 된 샘플입니다 :

참고 : 나는 자신을 도울 및 출력을 추가하지 못했습니다 프롬프트 난 당신에 대해 걱정한다고 생각하지 않는 문자열 입력 기능

-n test2.com 
-a 
0100: mov dx,100 ;100 is a placeholder for the address of output prompt 
0103: mov ah,9 
0105: int 21  ;output prompt 
0107: mov dx,100 ;100 is a placeholder for the address of the input buffer 
010A: mov ah,0a 
010C: int 21  ;read user input 
010E: int 20 
0110: db 48   ;"H" 
0111: db 65   ;"e" 
0112: db 6c   ;"l" 
0113: db 6c   ;"l" 
0114: db 6f   ;"o" 
0115: db 3a   ;":" 
0116: db 20   ;<space> 
0117: db 24   ;"$"/DOS strings terminated by dollar sign 
0118: db 0f   ;buffer member: hold 15 chars 
0119: db 00   ;buffer member: character input count stored here 

;the remainder of the .COM memory segment can be used to store the data 
; starting at address 11A 

;now that we know where our data fits, lets plug the addresses in 

-a 100 
0100: mov dx,110 ;address of "H" in prompt string 
-a 107 
0100: mov dx,118 ;address of input buffer with first two bytes reserved (see above) 
        ;max length to read and characters read 

-rcx 
CX 0000 
:1a 
-w 
Writing 001A bytes 

;lets run the program 

-g 
Hello: <lets assume you type "cat" followed by RETURN> 
Program terminated normally 

;now look at the 2nd byte in the buffer for the number of characters typed 
; along with the character data entered 

-d 118 11e 
0110   0F 03 63 61 74 0D 0D  ..cat.. 

이전 max 입력 chars 멤버를 정의한 후 버퍼 공간 확보; 버퍼가 프로그램의 끝에 있기 때문에 버퍼 공간으로 64k 세그먼트의 나머지 부분에 액세스 할 수 있습니다. (64KB에서 코드 및 환경 공간의 0x11b 바이트를 뺀 값).

편집 2016년 9월 11일 여기

는 사용자가 입력 한 것을 출력에 대한 질문을 해결하기 위해 (설명 포함) 수정 버전 :

0100 MOV  DX,0140 
0103 MOV  AH,09 
0105 INT  21   ;output prompt 
0107 MOV  DX,014B 
010A MOV  AH,0A 
010C INT  21   ;read user input 
010E MOV  DX,0148 
0111 MOV  AH,09 
0113 INT  21   ;output CRLF 
0115 MOV  DI,[014C]  ;load DI with value of characters read 
0119 AND  DI,00FF  ; MOV above read WORD, but we only want lower byte 
011D LEA  DI,[DI+014D] ;point DI to end of input string 
0121 MOV  AL,24   ;load DOS terminator char "$" in AL 
STOSB     ;write it to end input string 
0124 MOV  DX,014D 
0127 MOV  AH,09 
0129 INT  21   ;print the input string 
012B INT  20   ;exit program 

;I inserted NOPS until address 0140 so I would have room to insert code without my 
; data offsets changing 

0140 DB 48     ;"Hello: $" prompt begin 
0141 DB 65 
0142 DB 6C 
0143 DB 6C 
0144 DB 6F 
0145 DB 3A 
0146 DB 20 
0147 DB 24 
0148 DB 0D     ;CRLF$ sequence begin 
0149 DB 0A 
014A DB 24 
014B DB 20     ;Buffer begin (32 bytes max length) 
014C DB 00 

여러 가지 방법이 있습니다 CX 레지스터에 사용자 입력 수를로드하고 LOOP 명령을 사용하여 적절한 DOS 기능을 사용하여 각 문자를 인쇄하는 것과 같은 결과를 얻으십시오. 행운을 빕니다!

+0

와우는 훨씬 더 의미가 있습니다! 메모리에있는 캐릭터를 볼 수는 있지만 DL에 넣고 한 장씩 다시 인쇄하는 방법은 무엇입니까? 나는'mov DL, (메모리 위치)'를 사용하여 시도했으나 오류가있다. –

+0

DL이 바이트 크기이기 때문에 DL에 맞지 않는 WORD 주소 자체가 아닌 메모리의 내용을 이동하려는 괄호 안에 메모리 위치를 표시하지 않으면 오류가 발생합니다. 또한 debug.com은 "BYTE PTR"구문을 지원하지 않으므로 "mov"대신 "movsb"를 사용하여이를 암시해야 할 수도 있습니다. 예 : "movsb dl, [11a]" – byteptr

+0

완벽한! 나는이 조립 작업을 몇 년 동안 해본 적이 없다. 좋아, 내 문자열이 115에 있다고 말하면 첫 번째 문자는'[117] '에있다. ('mov DL, [117]') 만약'DL'으로 증가한다면 알파벳의 다음 문자를줍니다. 어떻게 문자열의 다음 문자, 즉'[118]'로 증가합니까? –

관련 문제