각 라인넘버는 프로그램의 파트가 아니다.
위 코드는 간단한 어셈블리어 코드로, Windows API 함수를 호출하여 프로그램을 종료하는 기능을 수행합니다.
해당 코드를 분석해보면:
- main proc 라인은 프로시저 선언을 나타냅니다. main 이라는 이름의 프로시저가 정의되고 있으며, proc 키워드를 사용하여 선언합니다.
- mov eax, 5 라인은 5를 EAX 레지스터에 저장합니다. EAX 레지스터는 일반적으로 값을 계산하거나 함수의 반환값을 저장하는 데 사용됩니다.
- add eax, 6 라인은 EAX 레지스터에 6을 더합니다. 따라서 EAX 레지스터에는 5+6=11이 저장됩니다.
- INVOKE ExitProcess, 0 라인은 Windows API 함수 중 하나인 ExitProcess 함수를 호출합니다. 이 함수는 프로그램을 종료하며, 0을 인수로 전달하여 정상 종료를 나타냅니다.
- 5.main ENDP 라인은 프로시저의 끝을 나타냅니다. ENDP 키워드를 사용하여 프로시저의 끝을 선언합니다.
따라서, 위 코드는 EAX 레지스터에 5와 6을 더한 결과를 구하고, 그 결과값을 출력하지 않고 프로그램을 종료하는 코드입니다.
CPU의 eax에 5를 저장하고, 6을 더하니 eax가 11이 된다.
윈도우가 제공하는 ExitProcess를 사용하여, 프로그램을 종료한다. ,0은 argument라 생각하면 된다. (return 0 같은 느낌이다.)
main ENDP는 메인 함수의 종료를 의미한다.
Saves the results of our addition in a variable named sum
해당 코드는 어셈블리어로 작성된 코드로, 간단한 변수 선언과 값을 할당하고 프로그램을 종료하는 기능을 수행합니다.
해당 코드를 분석해보면:
- .data 섹션에서 sum 이라는 이름의 DWORD 변수를 0으로 초기화합니다. 이 변수는 이후에 프로그램에서 사용될 수 있습니다.
- .code 섹션에서 main 프로시저가 정의됩니다. 프로시저는 PROC 키워드로 시작하여 ENDP 키워드로 끝나는 코드 블록입니다.
- mov eax, 5 라인은 5를 EAX 레지스터에 저장합니다.
- mov eax, 6 라인은 6을 EAX 레지스터에 저장합니다. 이전에 EAX 레지스터에 저장된 5는 더 이상 사용되지 않습니다.
- mov sum, eax 라인은 EAX 레지스터에 저장된 값을 sum 변수에 저장합니다.
- INVOKE ExitProcess, 0 라인은 Windows API 함수 중 하나인 ExitProcess 함수를 호출합니다. 이 함수는 프로그램을 종료하며, 0을 인수로 전달하여 정상 종료를 나타냅니다.
따라서, 위 코드는 sum 변수에 6을 저장하고 프로그램을 종료하는 코드입니다.
– [Line 2] the sum variable is declared
» We give it a size of 32 bits, using the DWORD size keyword
» Size keyworks only specify a size
– The code segment and the data segment
– Literals, identifiers, directives, instructions, …
sum DWORD은 데이터 세그멘트에 0을 저장
code segment가 이것저것 되어 있는 것이다.
MEM |
---|
0 |
△ 4칸 전부 sum이다 (4byte)
그런데, 다음으로 진행되면 0이 지워지고 아래와 같이 된다.
MEM |
---|
11 |
△ 4칸 전부 sum이다 (4byte)
An integer literal is made up of an optional leading sign, one or more digits, and an optional radix
character that indicates the number’s base
△
앞의 대괄호는 선택적으로 올 수 있다. (부호)
가운데 숫자는 무조건 나와야 한다.
뒤의 대괄호 radix(기수)도 선택적이다. 없으면 10진수를 나타난다.
– A hexadecimal literal beginning with a letter must have a leading zero
△ 16진수 수를 쓸 때는 0으로 시작하고 radix에 h를 쓴다.
표현식의 결과가 정수인데 항상 상수로 고정되는 것
– A mathematical expression involving integer literals and arithmetic operators
– Each expression must evaluate to an integer, which can be stored in 32 bits (0 through FFFFFFFFh)
– They can only be evaluated at assembly time
– Arithmetic operators
16/5를 하면, 계산이 runtime에 이루지는 게 아니라, 어셈블 타임(컴파일 할 때) 이루어진다.
그리고, 계산 된 결과는 32비트로 저장된다.
Represented as either decimal reals or encoded (hexadecimal) reals
2^23이면... 유효숫자가 80만? 정도밖에 표현을 못한다...
과학이나 수학 같이 큰 범위나 정밀한 결과를 원하면... 64비트를 써야 한다.
1 11 52비트로 나눠진다.
Decimal real은 일반적인 십진법 방식으로 나타낸 실수입니다. 즉, 소수점 이하 자릿수를 가진 수를 표현할 때 사용됩니다. 예를 들어, 0.5, 1.234, 3.141592 등은 모두 십진법 방식으로 표현된 decimal real입니다.
Encoded real은 컴퓨터에서 실수를 표현하기 위해 사용되는 방식 중 하나입니다. 실수를 표현할 때는 부호 비트, 지수 비트, 가수 비트 등으로 구성된 이진 형식을 사용합니다. 이진 형식에서는 소수점 이하 자릿수를 이진법으로 표현하여 저장합니다. Encoded real은 이러한 이진 형식으로 표현된 실수를 의미합니다.
Encoded real은 IEEE 754 표준과 같은 표준에 따라 표현됩니다. 이 표준은 32비트와 64비트 형태의 이진 부동소수점 표현을 제공하며, 부호 비트, 지수 비트, 가수 비트 등으로 이루어져 있습니다. 이진 형식을 사용하므로, decimal real과는 다르게 소수점 이하 자릿수가 정확히 표현되지 않을 수 있습니다.
△ 컴퓨터의 수 표현 하는 방법
예시를 들어 100000.01을 저장해 보자.
100000.01 => 1.000001 x 2^4 이므로,
0 00000100 100000100.... 이 된다
즉, 가운데 8비트는 2의 4승을 나타내고, 1.000001은 23비트에 저장된다.
여기다가, 2의 4승에서 나온 4에 127을 더해서 131이 되고,
1.000001에서 1을 생략해서 0.000001이 된다.
0 10000011 00000100....
최종적으로 위와 같이 정의된다.
예시2로 10.을 저장해보자.
10 => 1.0 x 2^1
0 10000000 000....이 된다.
40000000r 같이 뒤에 r이 붙으면 Encoded real이다.
1.0 => 1.0 x 2^0
문자 하나로 정의 된 상수를 말한다.
A sequence of characters (including spaces) enclosed in single or double quotes
String literals are stored in memory as sequences of integer byte values
• E.g.) the string literal “ABCD” contains the four bytes 41h, 42h, 43h, and 44h
예약어
(ADD 같은 것은 변수이름으로 쓸 수 없다.)
지시어, 어셈블리어에 의해서 인식되어 동작한다.
CPU가 메모리에서 Fetch(레지스터에서 옮겨오는...)해오는게 아니라 runtime에 실행되지 않는다.
변수, 함수 같은것을 정의하는 역할을 해준다.
memory segment에 이름을 정해줄 수 있다. (메모리 구획에..)
즉 A는 100번지라는 주소를 의미한다.
변수를 만드는 행위는 CPU가 하는 일이 이나디.
MEM (100번지) |
---|
3 |
메모리 4바이트 만큼, int A = 3이라 하면 위의 4칸에 3이라는 A변수가 저장된다.
하지만 B= A + 10; 이것은 CPU에서 실행되므로 Runtime에서 실행된다.
A를 불러올 때,
A command embedded in the source code that is recognized and acted upon by the assembler
(첫 줄은 CPU가 하는 일이 아니라, 어셈블러가 하는 일이므로 런타임 실행 아니고 어셈블이 됬을 때 실행된다.
두번째 줄은 eax레지스터에 myVar를 가져오는 것인데, CPU가 하는 일이다.)
어셈블리어의 핵심.
프로그램이 어셈블이 되면은(컴파일 되서 기계어로 번역되었다.) CPU
(단 Directives는 어셈블이 되지 않는다.)
명령어나 메모리의 데이터에 꼬리표(이름표)를 붙이는 것이다.
이 것은 명령어나 변수에 붙일 수 있다.
코드에 대한 레이블과 데이터에 대한 레이블이있다.
• An identifier that acts as a place marker for instructions and data
• There are two types of labels: Data labels and Code labels
– A label placed just before an instruction implies the instruction’s address
– A label placed just before a variable implies the variable’s address
• A data label identifies the location of a variable, providing a convenient way to reference the variable in code
- count DWORD 100
>> Defines a variable named count
- The assembler assigns a numeric address to each label
- You can define multiple data items following a label
>> array DWORD 1024, 2048
DWORD 4096, 8192
MEM |
---|
1024 |
- |
2048 |
연속해서 나오면, 메모리 안에서 인접해서 위치하므로 1024의 주소를 토대로 2048의 주소를 알 수 있으므로 2048의 이름을 지정하지 않아도 된다.
• A label in the code area of a program must end with a colon (:) character
• Code labels (코드 레이블)are used as targets of jumping and looping instructions
•
target:
mov ax, bx
...
jmp target
jmp 타겟은, target으로 점프하게 한다.
JMP instruction transfers control to the location marked by the label named target, creating a loop
• A code label can share the same line with an instruction, or it can be on a line by itself
- L1: mov ax, bx
L2
Label names follow the same rules we described for identifiers
• You can use the same code label more than once in a program as long as each label is unique within its enclosing procedure
변수나 레이블은, 중복해서 생성이 불가능하다.
(하나의 프로시저 안에서 중복 생성 불가능. 다른 프로시저는 가능한데... 다음에 다룰 것이다)
짧은 영어로 된 명령어...
• A short word that identifies an instruction
• Assembly language instruction mnemonics such as mov, add, and sub provide hints about the type of operation they perform
피연산자는 보통 하나나 두개를 쓰지만, 경우에 따라 세 개도 가능하다
피연산자는 방향이 있는데, 뒤에서 앞으로 이다. (destination source)
imul eax, ebx, 5 는 ebx에 5를 곱해서 eax에 저장
완전 선택사항.. 그냥 주석달기용임.
Single-line comments: 한 줄 주석
Block comments: 블럭 주석
특이한 인스트럭션인 NOP에 대해 알아본다.
아무일도 하지 않는 연산자이다.
교재에서 말하길 가장 안전한 명령어이자 쓸모없는 명령어이다.
정확하게, 1바이트를 차지한다.
MEM |
---|
.... |
0000 0000 0110 0110 |
0000 0000 1000 0000 |
0000 0000 1100 0011 |
0000 0000 1001 0000 nop |
- |
0000 0004 1000 1011 |
0000 0004 0110 0001 |
.... |
nop을 쓰는 이유는, 4바이트만큼 명령어를 끊어서 읽어 오는데, nop이 없으면
mov edx, ecx를 할 때 명령어가 갈린다. (밑에 000 0004부분이 nop으로 올라오면... 갈리는 것을 볼 수 있다.)
따라서 nop을 삽입해서 명령어가 안갈리게 만들어준다.
만약 명령어가 갈린다면 mov edx, ecx같은 경우엔 불필요하게 2번 읽어야지 수행 가능하게 된다.
그리하여, 효율적으로 동작이 가능하게 만든다.
△ 플랫한 모델을 쓰고, Function call에대한 convention이 저장되 있다... 정도로 알아두자
또한, 4킬로바이트 만큼 스택을 위해 공간을 할당 했다.
△
△ 윈도우에서 해당 실습을 돌리는 방법
△ 폴도 경로는 사람마다 다르다.
어셈블리어는 컴파일하고 링킹을 해야지 실행이 가능하다.
즉, 컴파일러와 링커는 나눠서 수행되어 진다.
어셈블링 하면 오브젝트 파일들을 링커로 하나로 합쳐서 실행..?
시스템 프로그래밍에서, 프로그램을 작성하고 실행하는 과정에는 주로 세 단계가 있습니다: Assembling, Linking, Running Programs. 아래에 각 단계에 대해 설명하겠습니다.
1.Assembling (어셈블링)
어셈블리 언어로 작성된 소스 프로그램은 바로 실행할 수 없습니다. 이를 실행 가능한 코드로 변환해야 하는데, 이 과정을 어셈블링이라고 합니다. 어셈블러는 컴파일러와 매우 유사한 역할을 수행합니다. 어셈블리 언어의 명령을 기계어 코드로 번역하여 실행 가능한 형태로 만드는 것이 주된 목표입니다.
2.Linking (링킹)
어셈블러를 통해 생성된 파일은 오브젝트 파일이라고 하며, 이 파일은 기계어로 작성되어 있습니다. 그러나 이 오브젝트 파일은 아직 실행할 준비가 되지 않았습니다. 왜냐하면, 다른 라이브러리나 모듈과 연결되어야 하기 때문입니다. 이러한 작업을 수행하는 프로그램을 링커라고 합니다. 링커는 오브젝트 파일과 다른 필요한 라이브러리를 결합하여 실행 가능한 파일을 생성합니다.
3.Running Programs (프로그램 실행)
링커를 통해 생성된 실행 가능한 파일은 이제 운영 체제에서 실행할 수 있습니다. 운영 체제는 실행 파일을 메모리에 로드하고, 프로그램의 시작 지점으로부터 명령을 실행하기 시작합니다. 프로그램이 완료되면, 결과가 반환되고, 운영 체제는 프로그램을 종료하게 됩니다.
요약하자면, 시스템 프로그래밍에서 프로그램을 실행하는 과정은 어셈블링, 링킹, 실행 프로그램의 세 단계로 이루어집니다. 어셈블러와 링커를 사용하여 소스 코드를 실행 가능한 형태로 변환하고, 이를 실행하는 과정을 거칩니다.
Assemble-Link-Execute Cycle은 프로그램을 작성하고 실행하는 과정을 단계별로 나타낸 것입니다. 이 과정은 다음과 같은 4단계로 이루어집니다:
소스 파일 작성
프로그래머는 텍스트 에디터를 사용하여 소스 파일이라고 하는 ASCII 텍스트 파일을 생성합니다. 이 파일에는 주로 어셈블리 언어로 작성된 코드가 포함되어 있습니다.
어셈블
어셈블러는 소스 파일을 읽어 기계어로 번역된 오브젝트 파일을 생성합니다. 선택적으로, 리스팅 파일도 생성할 수 있습니다. 만약 에러가 발생하면, 프로그래머는 [단계 1]로 돌아가 프로그램을 수정해야 합니다.
링킹
링커는 오브젝트 파일을 읽고 프로그램이 링크 라이브러리의 프로시저 호출을 포함하는지 확인합니다. 필요한 프로시저가 있다면, 링커는 링크 라이브러리에서 해당 프로시저를 복사하여 오브젝트 파일과 결합하고, 실행 가능한 파일을 생성합니다.
프로그램 실행
운영 체제의 로더 유틸리티는 실행 가능한 파일을 메모리에 읽어들이고, CPU가 프로그램의 시작 주소로 분기합니다. 그러면 프로그램이 실행되기 시작합니다.
Assemble-Link-Execute Cycle은 프로그램을 작성하고 실행하는 기본적인 프로세스입니다. 프로그래머가 소스 파일을 작성한 후, 어셈블러와 링커를 통해 실행 가능한 파일을 만들어낸 다음, 운영 체제에서 프로그램이 실행되는 것이 이 사이클의 전체 과정입니다.
△ 9~17번 줄에 보면 우리가 눈으로 볼 수 있는 번역한 언어가 있는데..
이것이 바로 리스팅 파일이다.
(공부하는 용으로 사용 가능하다... 그러니까 옵셔널 하다. 없어도 안돌아가는 건 아니니)
변수 명과, 그녀석의 테이블에 대한 것을 쭉 출력해준다.
Type | Usage |
---|---|
Byte | 8-bit unsigned integer. B stands for byte |
SBYTE | 8-bit signed integer. S stands for signed |
WORD | 16-bit unsigned integer |
SWORD | 16-bit signed integer |
DWORD | 32-bit integer. D stands for double |
SDWORD | 32-bit signed integer. SD stands for signed double |
FWORD | 48-bit integer (Far pointer in protected mode) |
QWORD | 64-bit integer. Q stands for quad |
TBYTE | 80-bit(10-byte) integer. T stands for Ten-byte |
REAL4 | 32-bit (4-byte) IEEE short real |
REAL8 | 64-bit (8-byte) IEEE long real |
REAL10 | 80-bit (10-byte) IEEE extended real |
Type | Usage |
---|---|
Byte | 8비트 부호 없는 정수. B는 바이트를 의미 |
SBYTE | 8비트 부호 있는 정수. S는 부호 있는(sign)을 의미 |
WORD | 16비트 부호 없는 정수 |
SWORD | 16비트 부호 있는 정수 |
DWORD | 32비트 정수. D는 더블(double)을 의미 |
SDWORD | 32비트 부호 있는 정수. SD는 부호 있는 더블(signed double)을 의미 |
FWORD | 48비트 정수 (보호 모드에서의 far 포인터) |
QWORD | 64비트 정수. Q는 쿼드(quad)를 의미 |
TBYTE | 80비트(10바이트) 정수. T는 텐 바이트(Ten-byte)를 의미 |
REAL4 | 32비트 (4바이트) IEEE 단정밀도 실수 |
REAL8 | 64비트 (8바이트) IEEE 배정밀도 실수 |
REAL10 | 80비트 (10바이트) IEEE 확장 실수 |
Directive | Usage |
---|---|
DB | 8-bit integer |
DW | 16-bit integer |
DD | 32-bit integer or real |
DQ | 64-bit integer or real |
DT | define 80-bit (10-byte) integer |
데이터 정의 문
Directive | Usage |
---|---|
DB | 8비트 정수 |
DW | 16비트 정수 |
DD | 32비트 정수 또는 실수 |
DQ | 64비트 정수 또는 실수 |
DT | 80비트 (10바이트) 정수 정의 |
데이터 정의 문은 변수를 생성할 때 사용되며, 내장 데이터 유형에 따라 메모리 공간을 할당합니다. 이름은 선택 사항이지만 변수를 식별하고 참조하는 데 도움이 됩니다. 지시문은 어떤 유형의 변수를 생성할지 결정하며, 초기화 값은 변수에 할당되는 초기 값입니다. 초기화 값은 변수의 유형에 맞는 정수 리터럴이나 정수 표현식이어야 하며, 여러 초기화 값이 있는 경우 쉼표로 구분됩니다. 또한, 변수를 초기화하지 않기를 원하면 ? 기호를 사용할 수 있습니다. 이러한 초기화 값은 어셈블러에 의해 이진 데이터로 변환되어 저장됩니다.
1: ; AddTwoSum.asm - Chapter 3 example
2:
3: .386
4: .model flat,stdcall
5: .stack 4096
6: ExitProcess PROTO, dwExitCode:DWORD
7:
8: .data
9: sum DWORD 0
10:
11: .code
12: main PROC
13: mov eax,5
14: add eax,6
15: mov sum,eax
16:
17: INVOKE ExitProcess,0
18: main ENDP
19: End main
Allocate storage for one or more unsigned or signed values
Each initializer must fit into 8 bits of storage
value 1 BYTE 'A' ; character literal
value 2 BYTE 0 ; smallest unsigned byte
value 3 BYTE 255 ; largest unsigned byte
value 4 SBYTE -128 ; smallest signed byte
value 5 SBYTE +127 ; largest signed byte
value 6 BYTE ?
The optional name is a label marking the variable’s offset from the beginning of its enclosing segment
The DB directive can also define an 8-bit variable, signed or unsigned
val1 DB 255 ; unsigned byte
val2 DB -128 ; signed byte
Multiple Initializers
list BYTE 10,20,30,40
Not all data definitions require labels
list BYTE 10,20,30,40
BYTE 50,60,70,80
BYTE 81,82,83,84
Within a single data definition, its initializers can use different radixes
list1 BYTE 10, 32, 41h, 00100010b
list2 BYTE 0Ah, 20h, 'A', 22h
greeting1 BYTE "Good afternoon",0
greeting2 BYTE 'Good night',0
greeting1 BYTE "Welcome to the Encryption Demo program""
BYTE "created by Kip Irvine.",0dh,0ah
BYTE "If you wish to modify this program please"
BYTE "send me a copy.",0dh,0ah,0
greeting1 \
BYTE "Welcome to the Encryption Demo program"
BYTE 20 DUP(0) ; 20 bytes, all equal to zero
BYTE 20 DUP(?) ; 20 bytes, uninitialized
BYTE 4 DUP("STACK") ; 20 bytes: "STACKSTACKSTACKSTACK"
4.BYTE와 SBYTE 데이터 정의하기
이 부분에서는 부호 있는 값 또는 부호 없는 값에 대한 저장 공간을 할당하는 방법을 배웁니다. 각 초기화 값은 8비트 저장 공간에 들어갑니다
예시는 아래와 같다.
선택적인 이름은 변수의 오프셋을 나타내는 레이블입니다. 여러 개의 초기화 값이 사용되는 경우, 해당 레이블은 첫 번째 초기화 값의 오프셋만을 가리킵니다.
예시는 아래와 같다.
모든 데이터 정의가 레이블을 필요로 하는 것은 아닙니다. 레이블로 시작된 바이트 배열을 계속 정의하려면 다음 줄에 추가 바이트를 정의할 수 있습니다.
예시
단일 데이터 정의에서 초기화 값은 다양한 진수를 사용할 수 있습니다.
이를 통해 다양한 형식의 데이터를 정의하고 초기화할 수 있으며, 이를 사용하여 프로그램에서 다양한 연산을 수행할 수 있습니다.
문자열 정의하기
DUP 연산자
word1 WORD 65535 ; largest unsigned value
word2 SWORD -32768 ; smallest signed value
word3 WORD ? ; uninitialized, unsigned
val1 DW 65535 ; unsigned
val2 DW -32768 ; signed
array WROD 5 DUP (?) ; 5 values, uninitialized
WORD와 SWORD 데이터 정의하기
16비트 정수를 위한 저장 공간을 생성합니다.
16비트 워드 배열을 만드는 예시:
Allocate storage for one or more 32-bit integers
val1 DWORD 12345678h ; unsigned
val2 SDWORD -2147483648 ; signed
val3 DWORD 20 DUP(?) ; unsigned array
val1 DD 12345678h ; unsigned
val2 DD -2147483648 ; signed
The DWORD can be used to declare a variable that contains the 32-bit offset of another variable
pVal DWORD val3
Array of 32-Bt Doublewords
myList DWORD 1,2,3,4,5
DWORD와 SDWORD 데이터 정의하기
하나 이상의 32비트 정수에 대한 저장 공간을 할당합니다.
DWORD는 다른 변수의 32비트 오프셋을 포함하는 변수를 선언하는 데 사용할 수 있습니다. 아래 예제에서 pVal은 val3의 오프셋을 포함합니다.
32비트 더블워드 배열을 생성하는 예시:
이렇게 정의하면 프로그램에서 32비트 정수 값을 저장하고 사용할 수 있습니다. 이를 통해 더 큰 정수 값을 처리하거나 메모리 주소와 같은 32비트 오프셋을 저장하는 데 사용할 수 있습니다.
quad1 QWORD 12345678h
quad DQ 12345678h
QWORD 데이터 정의하기
64비트(8바이트) 값을 위한 저장 공간을 할당합니다.
이러한 정의를 통해 프로그램에서 다양한 크기와 형식의 데이터를 저장하고 사용할 수 있습니다.
rVal1 REAL4 -1.2
rVal2 REAL8 3.2E-260
rVal3 REAL10 4.6E+4096
ShortArray REAL4 20 DUP(0.0)
rVal1 DD -1.2 ; short real
rVal2 DQ 3.2E-260 ; long real
rVal3 DT 4.6E+4096 ; extended-precision real
부동 소수점 유형 정의하기
1: ; AddVariables.asm - Chapter 3 example
2:
3: .386
4: .model flat,stdcall
5: .stack 4096
6: ExitProcess PROTO, dwExitCode:DWORD
7:
8: .data
9: firstval DWORD 20002000h
10: secondval DWORD 11111111h
11: thirdval DWORD 22222222h
12: sum DWORD 0
13:
14: .code
15: main PROC
16: mov eax,firstval
17: add eax,secondval
18: add eax,thirdval
19: mov sum,eax
20
21: INVOKE ExitProcess, 0
22: main ENDP
23: END main
10.리틀 엔디안 순서
.data
smallArray DWORD 10 DUP (0) ; 40 byte
.data?
bigArray DWORD 5000 DUP (?) ; 20,000 bytes, not initialized
,data
smallArray DWORD 10 DUP (0) ; 40 byte
bigArray DWORD 5000 DUP (?) ; 20,000 bytes
.code
mov eax,ebx
.data
temp DWORD ?
.code
mov temp,eax
11.초기화되지 않은 데이터 선언Symbol | Variable | |
---|---|---|
Uses storage? | No | Yes |
Value changes at runtime? | No | Yes |
심볼릭 상수
심볼 | 변수 | |
---|---|---|
저장 공간 사용? | 아니오 | 예 |
런타임에 값이 변경되나요? | 아니오 | 예 |
Count = 500
.
.
.
mov eax, Count
selfPtr DWORD $
Esc_key = 27
mov al,Esc_key ; good style
mov al,27 ; poor style
array dword COUNT DUP(0)
COUNT = 5
mov al,COUNT ; AL = 5
COUNT = 10
mov al,COUNT ; AL = 10
COUNT = 100
mov al,COUNT ; AL = 100
1.등호 지시문(Equal-Sign Directive)
list BYTE 10,20,30,40
ListSize = 4
list BYTE 10,20,30,40
ListSize = ($ - list)
myString BYTE "This is a long string, containing"
BYTE "any number of characters"
myString_len = ($ - myString)
list WORD 1000h,2000h,3000h,4000h
ListSize = ($ - list) / 2
list DWORD = 10000000h,20000000h,30000000h,40000000h
ListSize = ($ - list) / 4
2.배열과 문자열의 크기 계산하기
name EQU expression
name EQU symbol
name EQU <text>
PI EQU <3.1416>
pressKey EQU <"Press any key to continue...",0>
.
.
.data
prompt BYTE pressKey
matrix EQU 10 * 10
matrix EQU <10 * 10>
.data
M1 WORD matrix1
M2 WORD matrix2
M1 WORD 100
M2 WORD 10 * 10
name TEXTEQU <text>
name TEXTEQU textmacro
name TEXTEQU %constExpr
continueMsg TEXTEQU <"Do you wish to continue (Y/N)?">
.data
prompt1 BYTE continueMsg
rowSize = 5
count TEXTEQU &(rowSize * 2)
move TEXTEQU <mov>
setupAL TEXTEQU <move al,count> ; setup → mov al,10
여기서 설명하는 두 가지 지시어, EQU와 TEXTEQU는 어셈블리어에서 심볼과 값을 연결하는 데 사용됩니다. 이들은 코드를 더 간결하고 읽기 쉽게 만드는 데 도움이 됩니다.
3.EQU Directive
EQU 지시어는 심볼 이름을 정수 표현식이나 임의의 텍스트와 연결합니다. 세 가지 형식이 있습니다:
name EQU expression: expression은 유효한 정수 표현식이어야 합니다.
name EQU symbol: symbol은 이미 = 또는 EQU로 정의된 기존 심볼 이름입니다.
name EQU : 괄호 안에는 임의의 텍스트가 나타날 수 있습니다.
EQU 지시어는 정수로 평가되지 않는 값을 정의할 때 유용할 수 있습니다.
4.TEXTEQU Directive
TEXTEQU 지시어는 텍스트 매크로를 생성합니다. 세 가지 형식이 있습니다:
name TEXTEQU : text를 할당합니다.
name TEXTEQU textmacro: 기존 텍스트 매크로의 내용을 할당합니다.
name TEXTEQU %constExpr: 상수 정수 표현식을 할당합니다.
TEXTEQU는 다른 텍스트 매크로에 기반하여 새로운 매크로를 만드는 데 사용될 수 있습니다. TEXTEQU로 정의된 심볼은 언제든지 다시 정의될 수 있습니다.
EQU와 TEXTEQU의 주요 차이점 중 하나는 EQU로 정의된 심볼은 동일한 소스 코드 파일에서 다시 정의할 수 없지만, TEXTEQU로 정의된 심볼은 언제든지 다시 정의할 수 있다는 점입니다. 이로 인해 TEXTEQU는 코드를 수정하고 조정할 때 더 유연한 옵션이 될 수 있습니다.