(cf. intel의 x86-64 cpu의 assembly를 기준으로 진행.)
※ Assembly란?
기계어와 1:1 대응관계를 갖는 명령어의 집합체로 low-level 프로그래밍 언어이다.
- 물론 고급언어의 경우, 안전하고 편리하며 컴파일러를 통해 더 훌륭한 어셈블리 프로그램생성이 가능할지도 모른다.
assembly | High-level Language |
-대형 프로그램 개발이 불편
-속도가 중요한 응용프로그램, 하드웨어 직접 제어 시 이용
-임베디드 시스템의 초기코드 개발 시 이용
-플랫폼에 따라 새롭게 작성해야 해 이식성이 매우 낮음
-하지만 많은 간접적인 응용이 있음
- 배열이나 구조체 없이 메모리에서 연속적 byte들로 표시 |
-대형 프로그램 개발하기 매우 편함
-이식성이 높음 (high portability)
-비효율적 실행파일의 생성가능성이 존재
-대형 실용 응용프로그램 개발 시 이용
|
※ x86 processor
1978년부터 시작되어 점점 새로운 기능들을 추가하였지만, 예전의 기능들을 그대로 유지해 접근이 가능하다.
이런 intel의 철학은 바로 CICS (Complex Instruction Set Computer)로 다양한 형태의 명령어를 갖는다.
- EIP: 다음 명령어를 fetch해오는 주소 program counter
- Register File: Register의 집합
- Condition Code: 가장 최근 연산의 결과의 상태정보를 저장
- Memory: byte주소 지정가능한 배열로 명령어, data가 저장되며 stack이 존재한다.
※ x86-64의 정수 register
x86-64 processor(CPU)는 64-bit 값을 저장할 수 있는 16개의 register가 존재한다.
이들은 정수 데이터와 포인터를 저장하는 데, 포인터의 경우 주소를 저장하는데 사용합니다.
rsp, rbp와 같이 p로 끝나는 register의 경우가 바로 포인터를 사용해 주소를 저장하는 register이다.
이 16개의 레지스터는 모두 %r로 시작하는 이름을 갖는다.
위 사진을 보면 %rxx 레지스터의 절반의 크기에 %exx라는이름이 붙어있는 것을 확인할 수 있다.
%exx는 %rxx의 하위 4바이트에 해당하며 이와 같은 방식으로 아래 사진처럼 2바이트, 1바이트에 각각 접근가능!
이는 예전에 1바이트 단위 접근방식을 남겨두어 예전 의 기능을 그대로 유지해 하위 호완성을 유지하기 위해 과거의 레지스터들의 이름이 남아있는 것이다.
전체 16개의 레지스터의 하위 바이트들은 바이트, 워드(16비트), 더블워드(32비트), 쿼드워드(64비트)씩 접근할 수 있습니다.
※ 데이터의 이동 (Moving Data):
§ movq Source, Dest
위의 뜻은 Source를 읽어 Destination에 복사를 한다는 의미이다.
§ Operand의 유형
▶ Immediate : $로 시작하는 형태, 상수 정수 data
ex) $0x400, $-503▶ Register : %로 시작하는 형태, 16개 register지만 %rsp는 stack접근에만 이용한다.
ex) %rax, %r13
▶ Memory : (%register)의 형태, register로 지정되는 주소에 저장된 8개의 연속적 메모리 byte
- 이때, Memory주소지정을 다음과 같은 방식으로 할 수 있다.
i) 일반형 (R) = Mem[Reg[R]] ex) movq (%rcx) , %rax
ii) 변위형 D(R) = Mem[Reg[R] + D] ex) movq 8(%rbp) , %rdx
iii) 가장 일반적인 형태 D(Rb, Ri, S) = Mem[Reg[Rb] + S*Reg[Ri] + D]
- D: 상수 변위 (1, 2 or 4 bytes)
- Rb: base register : 16개 register 모두 가능
- Ri: index register : %rsp를 제외한 모두 가능
- S: 배율 (1, 2, 4 or 8 bytes)
이때, Dest에는 Immediate 즉, 상수값은 올 수 없다! (상수값에 대입할 수 없어서)
또한, Source와 Dest 모두 Memory인 memory-memory 데이터 이동은 한개의 명령으로 불가능하다.
Ex. 아래 함수에 대해 Assembly과정을 이해해보자.
<C code>
void swap (long *xp, long *yp) {
long t0 = *xp;
long t1 = *yp;
*xp = t1;
*yp = t0;
}
<Assembly>
swap:
movq (%rdi), %rax # t0 = *xp
movq (%rsi), %rdx # t1 = *yp
movq %rdx, (%rdi) # *xp = t1
movq %rax, (%rsi) # *yp = t0
ret
※ 주소 계산 명령어 (Load Effective Address):
§ leaq Src, Dst
- Src: 주소 모드 식 (Memory)
- Dst: 수식으로 표현된 주소값 저장 (Register)
용도: 메모리를 참조하지 않고 "주소만 계산"할 때 (C에서 &연산자, 곱셈과 같은 경우)
Ex. 아래 함수에 대해 Assembly과정을 이해해보자.
<C code>
long m12 (long x) {
return x * 12;
}
<Assembly>
leaq (%rdi, %rdi, 2) , %rax # t <- x + x*2
salq $2, %rax # return t << 2
leaq (%rdi, %rdi, 2) , %rax 부분을 통해 %rdi * 3과 같은 결과를 얻고
salq $2 (shift arithmetic left 2자리)연산을 이용해 (3 * %rdi) * 4로 최종적으로 12가 곱해지는 C code와 동일한 결과를 얻는다.
'Computer System > System Programming' 카테고리의 다른 글
this->sysp(05). assembly language III [procedure] ★★★★ (0) | 2022.12.25 |
---|---|
this->sysp(04). assembly language II [제어문] (0) | 2022.12.24 |
this->sysp(02). Data-Floating point [ IEEE floating point ] (0) | 2022.12.22 |
this->sysp(01). Data-Integer, [1 Byte = 8 bits] (0) | 2022.12.21 |
this->sysp(00). computer system (0) | 2022.12.21 |