[X86 어셈블리] strncpy 구현하기 / movsb 명령어 / 문자열
MOVSB, MOVSW, MOVSD
차례대로 Byte, Word, Doubleword 크기만큼 ds:si 레지스터가 가리키는 메모리 주소에서 es:di 레지스터가 가리키는 메모리 주소로 값을 복사한다. ds:si에서 ds 대신 다른 세그먼트 레지스터를 사용할 수 있지만 es:di에서 es 레지스터 대신 다른 세그먼트 레지스터를 쓸 수는 없다. 복사 후 si와 di가 증감한다. cld(clear direction)시 증가하고, std(set direction)시 감소한다.
STRNCPY 구현하기
movsb를 사용하여 n개의 문자를 복사하는 기능을 구현할 수 있다. 아래는 매크로로 구현된 strncpy이다.
TITLE STRNCPY
.DOSSEG
.8086
.MODEL TINY
.DATA
srcstr DB "Hello X86!$" ;11 chars including '$'
;srcaz DB "Hello X86!", 0 ;asciiz : null terminated string
strbuf DB 50 DUP (?)
.CODE
.STARTUP
;Copy n bytes from src to dst
strncpy MACRO dst, src, n
mov di, offset dst
mov si, offset src
mov cx, n
cld ;clear direction
rep movsb
ENDM
strncpy strbuf, srcstr, 11
;print dst buffer
lea dx, strbuf
mov ah, 9h
int 21h
mov ah, 4Ch
xor al, al
int 21h
END
어셈블 및 실행 결과
Dos 환경에서 MASM 6.11 버전으로 어셈블 후 실행
문자열의 끝에 대하여
위 코드에서는 'Hello X86!$'을 복사한다. 그런데 출력은 '$'가 빠진 'Hello X86!'이 출력된다. 그 이유는 DOS 21h 인터럽트 9번 함수[http://vitaly_filatov.tripod.com/ng/asm/asm_010.10.html] 호출로 문자열을 출력하는데 해당 함수가 '$'를 문자열의 끝으로 인식하기 때문이다.
즉 문자열의 끝을 '$'로 표시 해줘야 의도하는 방향(문자열 출력)으로 문자열을 활용할 수 있게 된다. Null character ('\0')으로 문자열의 끝을 표시하는 방법도 있지만 여기서 그렇게 할 경우에는 문자열 출력 시 쓰레기값 까지 출력하게 된다.
위 코드에서 주석처리된 srcaz 문자열을 source로 하여 복사를 수행한 후 문자열을 출력하면 다음과 같이 쓰레기값들까지 출력된다.
한편 파일을 여는 DOS 함수[http://vitaly_filatov.tripod.com/ng/asm/asm_010.62.html]는 null 문자로 끝나는 문자열을 파일명으로 받는다. 따라서, 내가 사용하는 문자열이 어떻게 저장되어야 올바르게 쓰일 수 있을 지 문서를 잘 읽고 코딩하는 것이 중요하다.