[MASM] ASSUME의 필요성?

gurumong의 이미지

80x6어셈블리어를 공부하고 있습니다
책의 예제에 쓰인 어셈블러가 MASM인데요
MASM의 지시어들중 한가지인 ASSUME에 대해서 설명을 하는데
도무지 이게 왜 필요한것인지 모르겠습니다

연산자(mov등)의 피연산자로 이름(name)이 사용되면
이름은 소스 코드내 유일하기 때문에 어려움없이 해당 세그먼트에서의 오프셋값을 계산할수있고
메모리 참조를 위해 기본 세그먼트 레지스터 사용을 가정하기에(DS:NAME) 아무런 문제없이 기계코드를 생성가능한데
왜 어셈블러에게 기계코드를 생성하지도 않는 ASSUME 지시어로 현재 사용중인 세그먼트의 이름을 알려줘야 할까요?

도와주세요! ㅜ,ㅜ

achrom의 이미지

예전에 정리한 글인데, 도움이 되시길 바랍니다.

-. All the addressing modes which use BP register for specifying offset
address use SS register as the default segment register, and all other
addressing modes for memory operand use DS register.

-. ASSUME
ASSUME은 MASM에게 뒤따르는 코드내에서 어떤 세그먼트가 세그먼트 레지스터와
연관되는지 알려주거나, 간접 메모리 참조에 사용될 크기를 알려준다. 지정하는
형태는 segreg:name 인데, 여기서 segreg는 CS, DS, SS 및 ES 중의 하나이고,
name은 SEGMENT 지시어를 사용하여 정의한 세그먼트 이름이거나 GROUP 지시어에
의해 정의된 그룹의 이름, 또는 세그먼트 주소를 나타내는 수식(SEG연산자를 이용한)
이다. 세그먼트 레지스터가 어떤 세그먼트와도 관련이 없으면 name 대신에 키워드
NOTHING을 사용한다.

가령, es:eseg의 의미는 다음과 같다.
eseg 안에서 정의된 변수를 사용할 때, 세그먼트 레지스터 es가 사용되어야 한다.
즉, 필요하다면 assembler가 적절한 segment override prefix를 사용하면서 번역해야 한다.
실제 runtime에서, es 레지스터에 해당 변수의 세그먼트 값이 미리 로딩되어야 할 것이다.

cs : 레지스터에 값을 수동으로 로딩할 필요는 없다.
ds, es : runtime에서 직접 로딩해야 할 것이다.

cs, es : segment prefix가 machine code에 삽입될 것이다.
ds : 대부분의 경우, 별도의 segment prefix가 필요없을 것이다.

다시 말하면, assume은 번역시 메모리 변수와 함께 사용될 segment를 미리 정하는 것이고,
assume을 사용하지 않거나, assume에서 정한 것과 다르게 사용하려면,
메모리 변수가 사용되는 위치에서 ds: 와 같은 segment prefix를 붙여주면 된다.
즉, C에서 정의된 변수를 assembly language에서 사용하려면, DS 등을 붙여서 사용하면 될 것이다.

==[1st example]============================================================================

sseg segment stack
db 64 dup(?)
sseg ends

dseg segment
db 100h dup (0)
array db 34h, 7fh, 2d, 0a4h
dseg ends

cseg segment para
assume cs:cseg, ds:dseg
; cseg 안에서 정의된 변수를 사용할 때, segment cs가 사용되도록 번역되어야 한다.
; dseg 안에서 정의된 변수를 사용할 때, segment ds가 사용되도록 번역되어야 한다.

begin: mov ax, dseg
mov ds, ax
mov si, 2
mov al, array[si]
; array는 dseg 안에서 정의된 변수이고, segment ds가 사용되도록 번역된다.
; 그러나, machine code 상에서 ds: 에 해당하는 3e는 삽입되지 않는다.
; 만약, assume 라인을 생략한다면, mov al, ds:array[si]와 같이 변경하면 된다.
; 이렇게 해도, 3e 는 삽입되지 않는다.
mov ah, 4ch
int 21h
cseg ends
end begin

==[2nd example]============================================================================

sseg segment stack
db 64 dup(?)
sseg ends

cseg segment para
assume cs:cseg
; cseg 안에서 정의된 변수를 사용할 때, segment cs가 사용되도록 번역되어야 한다.

var dw 1122H, 3344H
video db 80*25 dup(?)

begin: mov ax, 0b800h
mov es, ax
mov cx, 80*25
mov si, 0
mov di, 0
back: mov al, es:[di]
mov video[si], al
; cseg 안에서 정의된 변수를 사용할 때, segment cs가 사용되도록 번역되어야 한다.
; 여기서는 cs:에 해당하는 machine code 2e 가 삽입된다.
; 이상한 것은, assume 라인을 생략하면서, cs:를 붙여주지 않고 그대로 둬도 에러가 발생하지 않는다.
; 물론, 이 경우에도 2e는 삽입된다.
add si, 1
add di, 2
loop back
mov ah, 4ch
int 21h
cseg ends
end begin

==[3rd example]============================================================================
_OSIntCtxSw PROC FAR
;
CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook
;
MOV AX, SEG _OSTCBCur ; Reload DS in case it was altered
MOV DS, AX ;
; _OSTCBCur 의 segment 값을 실제로 loading.

MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy
MOV DX, WORD PTR DS:_OSTCBHighRdy ;
; Segment로는 ds를 offset으로는 _OSTCBHighRdy를 사용하여 변수값을 접근.
; 실제로는 3E가 machine code로는 삽입되지 않을 것이다.

MOV WORD PTR DS:_OSTCBCur+2, AX ;
MOV WORD PTR DS:_OSTCBCur, DX ;
; Segment로는 ds를 offset으로는 _OSTCBCur를 사용하여 변수값을 접근.

MOV AL, BYTE PTR DS:_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy
MOV BYTE PTR DS:_OSPrioCur, AL
;
LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr
; segment로는 ds, offset으로는 _OSTCBHighRdy인 변수의 주소를 ES:BX 로 대입.
; 즉, DS -> ES, OFFSET OF _OSTCBHighRdy -> BX가 될 것이다.

MOV SS, ES:[BX+2] ;
MOV SP, ES:[BX] ;
;
POP DS ; Load new task's context
POP ES ;
POPA ;
;
IRET ; Return to new task
;
_OSIntCtxSw ENDP

PAGE ; /*$PAGE*/

gurumong의 이미지

ASSUME 지시어는 기계어로 변환이 안되어지는걸로 알고있는데요
단지 세그먼트 레지스터가 어떤 세그먼트와 연관되는지 어셈블러에게 정보를 알려주는 정도라고 알고있는데
이렇게 알려준 정보를 어셈블러가 어떻게 활용하는지 잘 모르겠습니다 ㅜ.ㅜ

처음엔 책의 설명을 읽고 이해하기에
ASSUME로 현재 세그먼트 레지스터가 어떤 세그먼트를 가르키고 있는지 알려주고
DB, DW 등으로 정의된 메모리변수에 이름이 붙여주면
코드상에서 유일한 그 메모리변수 이름이 사용될적에
(메모리변수가 어느 세그먼트에 정의되어있는지 알고 현재 CS,DS,SS,ES가 어떤 세그먼트를 가르키는지 알기에)
자동적으로 필요에 따라 오버라이드 세그먼트 접두어를 붙여주는줄 알았는데 아니더라구요

익명사용자의 이미지

위의 설명에 덧붙이자면...

segment prefix가 생략되는 경우는 크게 2가지입니다. 일반적인 데이터 이동 명령은 기본적으로 DS:가 붙은 것으로 가정합니다. 따라서 DS:에 해당하는 segment prefix는 강제로 지정해도 생략됩니다. SP와 BP 레지스터가 참조하는 메모리는 기본적으로 SS:가 붙은 것으로 가정합니다. 따라서 이 경우에도 SS:는 생략됩니다. 그 외의 경우에는 강제로 segment prefix를 붙여주는 것이 좋습니다. (assume문은 segment prefix를 생략해주는데는 유용하지만 강제로 붙여주는 것을 기대하지는 않는 편이 좋습니다.)

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.