코드 여기저기에 500이라는 수를 직접 쓰는 대신 COUNT라는 이름을 지어 두고 이름을 쓴다. 어셈블러는 기계어로 옮기기 전에 이름을 그 값으로 바꿔 넣으므로, 이름은 메모리를 한 칸도 차지하지 않는다. 값이 바뀌면 한 줄만 고치면 되고, 배열의 크기처럼 손으로 세기 귀찮은 값은 어셈블러가 대신 세게 할 수 있다. 다만 크기를 세는 줄은 배열 정의 바로 다음에 두어야 맞는 값이 나온다.
예시로 보기
배열에 값이 몇 개 들었는지 코드에 4라고 직접 써 두면, 배열에 값을 하나 더 넣는 날 그 4를 찾아 모두 고쳐야 한다. 하나라도 놓치면 프로그램은 조용히 틀린다. 어셈블러에게 세게 하면 이 걱정이 사라진다.
어셈블러는 데이터를 놓아 가면서 “다음 바이트가 들어갈 자리”를 늘 기억한다. 그 자리를 $로 쓴다. 배열을 다 놓은 직후의 $에서 배열이 시작한 자리를 빼면 배열의 바이트 수다.
list BYTE 10,20,30,40
ListSize = ($ - list)
오프셋 0 1 2 3 4
바이트 0A 14 1E 28 (다음 자리)
▲ ▲
list $
$는 4, list는 0이라 ListSize는 4다. list가 어디서 시작하든 차이는 같다.
$ - list가 4, 8, 16인 것, 시작 주소를 바꿔도 같은 것, 사이에 변수가 끼면 틀리는 것, 카드 C1·C2. 파이썬 흉내로 확인 — 14_symbolic-constants_verify.py정의
기호 상수는 정수 식이나 글에 붙인 이름이다. 만드는 지시어가 둘 나온다.
등호 지시어 = |
EQU 지시어 |
|
|---|---|---|
| 쓰는 법 | 이름 = 식 |
이름 EQU <글> 등 |
| 붙일 수 있는 것 | 32비트 정수(식이나 상수) | 정수 식이나 글 |
| 같은 이름을 다시 정하기 | 된다 | 안 된다 |
| 근거 |
COUNT = 500
.
.
mov ax,COUNT ; mov ax,500과 같다
PI EQU <3.1416>
pressKey EQU <"Press any key to continue...",0>
.data
prompt BYTE pressKey ; prompt BYTE "Press any key to continue...",0과 같다
수 대신 이름을 쓰는 것이 좋은 프로그래밍 습관이다.
위치 카운터 $는 지금 놓고 있는 자리의 주소다. 배열 바로 다음 줄에서 배열의 시작 주소를 빼면 바이트 수가 나온다. 원소가 1바이트보다 크면 원소 하나의 크기로 나눠야 개수가 된다.
list WORD 1000h,2000h,3000h,4000h
ListSize = ($ - list) / 2 ; 8 / 2 = 4
list DWORD 1,2,3,4
ListSize = ($ - list) / 4 ; 16 / 4 = 4
예제
세는 줄을 떨어뜨리면 틀린다.1
list BYTE 10,20,30,40
other BYTE 1,2
ListSize = ($ - list) ; 6. list의 크기 4가 아니다
$는 “지금 자리”일 뿐 list의 끝을 아는 것이 아니다. 사이에 other가 놓이면 그 2바이트까지 센다.
활용
- 기호 상수는 어셈블할 때 값으로 바뀌어 사라진다. 실행 파일에
COUNT라는 칸은 없다1. 지시어가 어셈블러에게 하는 말이라는 점은 지시어와 명령어 비교와 같다. - 강의 목차에는
TEXTEQU지시어도 있지만 설명하는 쪽은 없다. - 같은 일을 하는 연산자가 뒤에 나온다.
LENGTHOF list는 원소 개수,SIZEOF list는 바이트 수를 준다: TYPE·LENGTHOF·SIZEOF 연산자. - 흔한 실수: 워드 배열에서 2로 나누는 것을 잊어 개수가 두 배로 나온다.
연결
- 선수: 지시어와 명령어 비교, 데이터 정의
- 이름이 값으로 바뀌는 때: 어셈블·링크·실행 과정
확인 문제
C1 list WORD 5 DUP(0),7 바로 다음 줄에 ListSize = ($ - list) / 2를 썼다. ListSize는 얼마인가?
답: 6.
이유: 워드가 5개 + 1개 = 6개라 12바이트다. $ - list가 12, 2로 나누면 6이다. 나누지 않으면 바이트 수 12가 나온다.
C2 “ListSize = ($ - list)는 어디에 써도 list의 바이트 수다”가 틀렸음을 보이는 데이터 정의를 만들고, 그때의 ListSize를 쓰라.
답: 예: list BYTE 1,2,3 / other BYTE 9,9 / ListSize = ($ - list). ListSize는 3이 아니라 5다.
이유: $는 그 줄에 이르기까지 놓인 모든 바이트의 다음 자리다. list와 세는 줄 사이에 다른 데이터가 놓이면 그것까지 센다.
C3 프로그램 앞쪽에서 SIZE를 10으로 쓰다가 뒤쪽에서 20으로 바꿔 쓰고 싶다. =와 EQU 가운데 무엇으로 정의해야 하는가? 다른 쪽은 왜 안 되는가?
답: =. SIZE = 10으로 정하고 뒤에서 SIZE = 20으로 다시 정한다.
이유: =로 만든 이름은 다시 정할 수 있고, EQU로 만든 이름은 다시 정할 수 없다. 대신 EQU는 <…> 안에 글을 통째로 붙일 수 있다.