2017-11-30 3 views
2

저는이 책에서이 어셈블리 프로그램을 연구했으며 그것에 대해 질문이 있습니다. 이 프로그램의 목적은 단순히 string1을 string2에 복사하는 것입니다. 내 질문은 다음과 같은 두 가지 지시 사항에 관한 것이다조립 문자열 지침 DS 및 ES를 리얼 모드로 등록하십시오.

내가 그들없이 볼
mov AX,DS   
mov ES,AX 

, 프로그램이 제대로 작동하지 않는,하지만 난 문자열 1을 ESI을 지정하여 생각이나 했 겠어요 및 EDI 그 모든 당신이 필요로하는 것, 문자열 2 할 할 것. 그런 다음 ESIEDI 만 증가시키고 문자 단위로 이동하십시오. DS은 정확히 무엇을 보유합니까? ES으로 이동해야하는 이유는 무엇입니까? EDI 사용 ES:EDI를 사용

.DATA 
string1 db 'The original string',0 
strLen  EQU $ - string1 
.UDATA 
string2 resb 80 
.CODE 
    .STARTUP 
    mov AX,DS   ; set up ES 
    mov ES,AX   ; to the data segment 
    mov ECX,strLen  ; strLen includes NULL 
    mov ESI,string1 
    mov EDI,string2 
    cld     ; forward direction 
    rep movsb 
+0

이 16 비트 코드입니까? 만약 당신이 정말로 CX, DS, DI를 사용해야합니다. 그리고 나는 당신이'mov ESI, offset string1'과'mov EDI, string1'을 의미한다고 가정하니? –

+0

이것은 책에서 나 왔으며 책에서 지정하지 않았습니다. – Rubiks

+0

windows dosbox 및 nasm – Rubiks

답변

3

모든 문자열 지침을 제공합니다. EDI (같은 [edi]) DS 기본적하지만 movs/stos/scas/cmps (with/without rep/repz/nz) all use es:edi를 사용하여 (또는 di 또는 rdi)

명시 주소 모드. lodsds:esi 만 사용합니다. (rep lods는 "작동", 드물게 유용합니다. CX와 = loop 달리, rep 점검 감소시키는 전에 cx. 있기 때문에, 느린 조건 부하로 동작 할 수 있습니다 0 또는 1)

참고 비록 scas가 읽기 전용 있음 (r|e)di을 사용합니다. 이렇게하면 lods : lods, scas과 같은 배열의로드가 다른 배열과 비교할 때 잘 작동합니다. (임의로 비교하기 전에 (r|e)ax의 처리와 함께).


일반적으로 32 비트 주소를 사용할 수있는 경우 모든 세그먼트의 기본 및 제한이 동일한 플랫 메모리 모델이 있습니다. 또는 NASM을 사용하여 .COM 플랫 바이너리를 만드는 경우 모든 세그먼트의 값이 동일한 작은 리얼 모드 메모리 모델을 사용할 수 있습니다. @ MichaelPetch의 덧글 on this answeron the question을 참조하십시오. ES을 설정하지 않고 프로그램이 작동하지 않으면 이상한 일을하고 있습니다. (같은 아마 어딘가에 es을 건드리지?) 주소 크기 접두사없이 rep movsb에서 16 비트 모드가 CX, DS:SIES:DI를 사용하는

주에 관계없이 당신이 피연산자 크기의 접두사를 사용하는지 여부 edi 대신 di를 작성합니다.


또한 종종 ** 것들을을 할 수없는 가장 빠른 방법을 그 담당자 문자열 지침 (특히 비 대표 버전)를 확인합니다. 코드 크기에 적합하지만 SSE/AVX 루프보다 느립니다.

rep stosrep movs은 16 또는 32 바이트 (또는 Skylake-AVX512에서는 64 바이트)의 청크로 저장하거나 복사하는 빠른 마이크로 코드 구현이 있습니다. Enhanced REP MOVSB for memcpy을 참조하십시오. 32 바이트 정렬 포인터와 중 ~ 대형 버퍼 크기로 최적화 된 AVX 루프만큼 빠릅니다. 최신 CPU에서 128 또는 256 바이트 미만의 크기 또는 정렬되지 않은 포인터를 사용하면 일반적으로 AVX 복사 루프가 이깁니다. Intel의 최적화 설명서에는 이에 대한 섹션이 있습니다.SSE2를 사용하거나 마이크로는 여전히 한 번에 바이트를 비교하기 때문에 AVX2 SIMD는 (pcmpeqb) 비교 :

그러나 repne cmpsb 확실히 memcmp을 구현하는 가장 빠른 방법이 아니다. (특히 버퍼의 끝을 지나쳐 읽는 것을 조심하십시오, 특히 페이지 (또는 선호 캐시 라인) 경계를 넘지 않도록하십시오.) 어쨌든 repne/repe에는 Intel 또는 AMD CPU에서 "빠른 문자열"최적화가 이루어지지 않습니다.

+1

그냥 - 혼란 - Op-With-More-Information : 문자열 명령어의 "소스"와 유사한 부분은 세그먼트 접두사 opcode로 덮어 쓸 수 있습니다. 즉,'es lodsb'는'[es : si]'. 그러나 "대상"과 같은 것은'es : di'에만 연결되어 있으며'ds stosb'와 같은 세그먼트 접두사는 무시됩니다. – Ped7g

+0

SIMD는 코드를 작성할 때 특별히주의하지 않는 한 메모리 영역 끝을지나 읽을 수 있다는 단점이 있습니다. 이것은 합리적으로 다루기가 짜증나게합니다. – fuz

+1

더 나은 질문은 사용자가 DS를 복사해야하는 이유에서 그가 환경을 사용하고 있는지입니다. NASM은 EXE가 아닌 COM 프로그램을 생성하고 COM 프로그램은 CS = DS = ES = SS로 시작합니다. 개인적으로 질문은 스 니프 테스트를 통과하지 않으며 최소한의 완전한 예가 아닙니다. 게시 된 코드는 그대로 (io.mac가 필요하기 때문에) 컴파일되지 않으며'org 0x100' 지시자를 올바르게 작동시킵니다. –