지난주에 이어서 서브루틴 사용에 유용한 명령 3개에 대해 읽었다.
Assembly language features
1. PREFIX
프로그램이 큰 경우 레지스터 뿐 아니라 심볼명도 중복되는 일이 생길 수 있다. 그래서 일종의 네임스페이스를 지정해서 일정 범위 안의 심볼을 특정 prefix 범위 안으로 묶을 수 있다. 네임스페이를 지정하는데에는 콜론(:)을 사용한다.
- 콜론(:)으로 시작하지 않는 심볼은 모두 current prefix 가 앞에 붙은 것으로 간주한다.
- current prefix 의 기본값은 “:” 이다.
- PREFIX 명령으로 current prefix 를 갱신할 수 있다.
... # current prefix ":" (default)
ADD x,y,z
PREFIX Foo: # current prefix "Foo:"
ADD x,y,z
PREFIX Bar: # current prefix "Foo:Bar:"
ADD :x,y,:z
PREFIX : # current prefix ":"
ADD x,Foo:Bar:y,Foo:z
...
2. LOCAL
특정 expression 이 지역(local) 레지스터임을 보장하는 assertion 이다. 예를 들어,
LOCAL $40
이렇게 하면 \$40 은 전역 레지스터로 쓰일 수 없다.
3. BSPEC .. ESPEC
특정 데이터를 별다른 처리를 하지 않고 그냥 저장하는 섹션을 만든다. 프로그램이 알아서 사용할 바이너리 데이터로, 리소스나 메타정보 등을 저장한다. XML 의 <![CDATA[ … ]]> 와 비슷한 느낌이다.
컴파일러나 링커 등이 Linkage 를 알아 내기 위해서도 사용한다고 한다.
BSPEC 42
TETRA 1,2,3
ESPEC
BSPEC 뒤에는 0 ~ 255 사이의 정수가 올 수 있다. GNU Binutils 에서 80 을 사용한다.
Strategic considerations
큰 라이브러리에 포함될 일반적인 서브루틴을 만드는 경우 단 하나라도 전역 레지스터를 사용하는 것은 큰 부담이 될 수 있다. 수백개 이상의 서브루틴이 각자 전역 레지스터를 하나씩 내놓으라고 하면 어쩌겠는가? 길고 복잡한 프로그램을 작성하는 전략(?)에 대하여 Knuth 님이 정리해 주셨다.
- Initial idea
- A rough sketch of the program
- First working program
- Reexamination
- Debugging
Silly
Gsong 님이 1.3.2 의 연습문제 5번,
What do you get from 'BYTE 3+"pills"+6' ?
에 대해 질문하셨다. 책 뒤에 답이 있긴 하지만 왜 그 답이 나오는 지를 모르겠다는 것.
비밀은 책 어딘가세 설명되었던 BYTE 의 동작에 숨어있다. BYTE "abc"
는 MMIXAL 에 의하여
BYTE 97,98,99
로 치환된다. 이 치환 작업이 BYTE 명령의 피연산자의 계산 이전에 일어난다. 마치 C Macro 처럼.
pills
의 아스키 코드는 112, 105, 108, 108, 115
인데 이 치환 작업을 위의 코드에 넣으면 아래와 같이 변한다.
BYTE 3+"pills"+6
BYTE 3+112,105,108,108,115+6
BYTE 115,105,108,108,121
얻어진 아스키 코드 115,105, 108, 108, 121
를 텍스트로 나타내면,
>>> ''.join(map(chr, [115,105, 108, 108, 121]))
'silly'
silly 가 된다.
스터디 마무리는 이 사진으로:
Comments