데이터 연산

·2024년 4월 18일

컴퓨터 구조

목록 보기
8/11
post-thumbnail

Moving Data

movq Source, Dest;

(q 가 붙는건 64 bit라서~)

피연산자 유형을 살펴보자 ❓🫡

immediate: 상수

  • ex. $0x400, $-533,..
  • c와 비슷하나, $로 접두사가 붙는다
  • 1,2, 4 byte로 인코딩된다
  • 데이터를 바로 사용가능하기 때문에 immediate이다

register : 16개 정수 레지스터 중 하나이다.
ex. %rax, %r13,..
%rsp 는 특별한 용도로 예약되어 있다 (Stack pointer)
다른 레지스터도 특정 명령에 대해 특수한 용도로 사용될 수 있다

memory : 레지스터가 가리키는 주소에 있는 8개의 연속된 바이트 메모리

  • 간단한 ex. (%rax) ** rax 주소내의 값!을 원할 때 괄호를 해요 . ㅇㅋ? 괄호 없으면 걍 주소고여.

movq Operand Combinations 😎

movq

sourcedestsrc,destC analog
immregmovq $0x4,%raxtemp = 0x4;
memmovq $-147, (%rax)*p = -147;
regregmovq %rax,%rdxtemp2 = temp1;
memmovq %rax,(%rdx)*p = temp;
memregmovq (%rax),%rdxremp=*p;

소스가 상수인 경우, register인 경우 , 메모리인 경우로 나눠서 알아보자.

+) 상수는 공간이 아니라서 dest 는 불가해 ^^

+) Src 일 때와 Dest 일 때 역할이 달라.

src : 레지스터/메모리에 저장된
dst : 레지스터/메모리 공간

=> 공간을 넣는다 이말이야. 🤗

몇 개 해석을 해보자면(위에서부터)

❤️movq $0x4,%rax : 상수 0x4를 레지스터 %rax 에 저장한다

❤️movq $-147, (%rax) : 상수 -147을 메모리주소 (%rax)에 저장한다.
=> _%rax가 가리키는 메모리 주소_에 값-147 이 저장되는거임

❤️movq %rax,%rdx  : 레지스터 %rax 에 있는 값을? 레지스터 %rdx 로 복사한다 

그니까 %rdx 레지스터에는 %rax 레지스터에 있는 값이 복사된다 이말임.

❤️movq %rax,(%rdx) : 
레지스터 %rax 에 있는 값을 레지스터 %rdx 가 가리키는 메모리 주소에 저장하는 역할. 
긍까 _%rdx 레지스터가 가리키는 메모리 주소_에? 
%rax 레지스터에 있는 값이 저장되는거임    

❤️movq (%rax),%rdx  :  레지스터 %rax 가 가리키는 메모리 주소에 있는 값을 ? 
레지스터 %rdx 에 복사하는 역할. 
긍까 %rax 가 가리키는 메모리 주소에 있는 값이 %rdx 레지스터에 복사된다
이말임.

(괄호안은 위에서 말했듯이 그 주소 내의 값..인디
긍까 그 주소 내의 값을 ~ 이라고 되는거임)


***** 하나의 명령어로 레지스터-레지스터 전송은 가능하나
메모리-메모리 연산은 불가해요 

간단한 메모리 주소 지정 모드

일반적.

❤️(R) 	Mem[Reg[R]] 

일반적인 R은 메모리의 레지스터 R에 저장된 값을 가리키는 포인터를 나타낸다.

이것은 메모리의 주소가 레지스터 R의 값에 의해 결정된다는 것을 의미한다

movq (%rcx), %rax

레지스터 R 은 메모리 주소를 지정하는 것으로 ,
C 에서는 포인터역참조와 유사하다.

movq (%rcx), %rax는 %rcx 레지스터의 내용이 가리키는 메모리 위치에 있는 값을 %rax 레지스터로 로드한다

int *ptr;
int num1 = 10;

ptr = &num1;

printf("%d\n", *ptr); 
// 역참조 연산자로 num1의 메모리 주소에 접근하여값을 가져옴 

C 로 비교하자면 얘 🙄랑 비슷하다고 생각하면 돼요

❤️이동 D(R)	Mem[Reg[R]+D]

이동(D) 은 메모리의 레지스터 R 에 저장된 값에 오프셋을 더하는 것을 나타낸다.

이것은 메모리 주소가 레지스터 R 의 값에 오프셋 D 를 더하여 결정된다는 것을 의미한다

movq 8(%rbp),%rdx

레지스터 R 은 메모리 영역의 시작을 지정하고,
상수 이동값 D는 offset 을 지정한다.

movq 8(%rbp), %rdx 는
%rbp 레지스터에서 8 바이트 offset 에 위치한 메모리 위치값을
%rdx 레지스터에 로드한다.

그니까
8(%rbp) ==>걍 base address 인 %rbp메모리 주소에서 8 떨어진 애를 지칭

address modes( 주소 모드 )

❤️일반적인 형태

  • D(Rb,Ri,S) Mem[Reg[Rb]+S*Reg[Ri]+D]

  • D: displacement로, 상수. 1,2,4 byte 와 같은 값으로 메모리 위치 조절

  • Rb : base register : 16개 정수 레지스터 중 하나 사용 가능

  • Ri: index register: %rsp 를 제외한 어느 레지스터든 가능함요

  • S: scale, 주소 계산에 사용되는 정수. 1,2,4,8 과 같은 2의 거듭제곱 값을 가진다(이 값들은 비트 시프트에 사용되기 때문~)

❤️특수한 경우

  • (Rb,Ri) Mem[Reg{Rb]+Reg{Ri]]
    : 이 경우에는 Ri의 값이 스케일링되지 않고, Rb와 Ri 레지스터 값의 합으로 메모리 주소가 결정된다

  • D(Rb,Ri) Mem[Reg[Rb]+Reg[Ri]+D]
    : 이 경우에는 상수 D가 Ri의 값과 함께 사용되며, Rb와 Ri 레지스터 값의 합에 D가 더해져 메모리 주소가 결정된다

  • (Rb,Ri,S) Mem[Reg[Rb]+S*Reg[Ri]]
    : 이 경우에는 스케일링된 Ri의 값이 Rb와 함께 사용되며, 스케일링된 값과 Rb 레지스터 값의 합으로 메모리 주소가 결정된다

조금 더 세세하게 알아봅세다

(Rb,Ri) Mem[Reg[Rb]+Reg[Ri]]

🍎movq(%rbx,%rcx), %rax

:(rbx + rcx) == 메모리주소겠져?
그 메모리 주소 안의 값을
%rax에 옮기세요 !

D(Rb,Ri) Mem[Reg[Rb]+ Reg[Ri]+D]

🍎movq 16(%rbx, %rcx), %rax

: (rbx+rcx) + 16 에 저장된 값!! 을
rax에 저장하세요 !

(Rb,Ri,S) Mem[Reg[Rb]+S*Reg[Ri]]

🍎movq (%rbx,%rcx,8), %rax

: rbx + 8xrcx 에 저장된 값 !! 을
rax 에 저장하세요 !!

cf) movq (%rbx,%rcx,1) == (%rbx,%rcx)
1 곱하나마나니깐 ~~

산술 및 논리 연산

address computation instruction

leaq Src,Dst(load effective address quadword)
-- 주소 읽어오기! 가 목적입니다요.

  • src 는 주소 모드 표현식이고, 이 표현식이 나타내는 주소를 dst 에 설정한다.

  • 이런 상황에서 쓴다 !

    메모리 참조 없이 주소를 계산할 때.
    ex. p = &x[i]; 와 같이 배열 인덱싱 연산 번역시..

    형식이 x+k*y 인 산술식을 계산할 때 ( 여기서 k 는 1,2,4,or 8)

(lea ... 주소 읽어오기가 목적이었으나 산술연산에도 활용됩니당 )

some arithmetic operations

two operand instructions:

🤍addq src,dest
🤍subq ..
🤍imulq(int multiply 정수곱이라는뜻)
🤍salq(shift arithmetic left quadword) dest = dest << src
🤍sarq dest = dest >>src
🤍shrq(shift right) cf) shl은 ...? left 은 왜 없성. ->left 는 msb 채우는거 딱히 의미없어서요
dest = dest >> src

        이거 다 shift 연산인디 차이 그거야 arithimatic 인지 logical
        ( 0 걍 채우는거랑 msb 채우는거 있었자넝 .)
        

🤍xorq dest = dest ^ src
🤍andq dest = dest& src
🤍orq dest = dest|src

cf)인수의 순서 주의하기.
cf)imulq 제외하고는 부호 있는 정수와 부호 없는 정수에 차이가 없음요 .

왜냐구 ??
동일한 명령어가 부호 있는 정수와 부호 없는 정수 모두에 대해 산술을 수행할 수 있으니깐 ..~

결과의 해석은 연산이 수행되는 맥락에 따라 달라짐.

one operand instructions(피연산자 하나인 연산)

🤍incq dest 💙dest = dest+1
🤍decq dest 💙dest = dest-1
🤍negq dest 💙dest = -dest
🤍notq dest 💙dest = ~dest

연습을 한번 해보자 ㅇㅋ ?

long arith
(long x, long y, long z)
{
long t1 = x+y;
long t2 = z+ t1;
long t3 = x+ 4;
long t4 = y * 48;
long t5 = t3 + t4;
long rval = t2* t5;
return rval;
}

arith:

leaq (%rdi,%rsi), %rax 	#t1
addq %rdx,%rax			#t2
leaq (%rse,%rsi,2), %rdx
salq $4, %rdx			#t4
leaq 4(%rdi,%rdx), %rcx	#t5
imulq %rcx, %rax		#rval
ret
registeruse(s)
%rdiargument x
%rsiargument y
%rdxargument z
%raxt1,t2,rval
%rdxt4
%rcxt5

연산과정해설

leaq (%rdi,%rsi), %rax: 
레지스터 %rdi에 있는 값(x)과 
%rsi에 있는 값(y)을 더한 결과를 %rax 레지스터에 로드합니다. 
이 값은 t1에 해당합니다.

addq %rdx, %rax: 레지스터 %rdx에 있는 값(z)를 t1에 더한 결과를 %rax 레지스터에 저장합니다. 이 값은 t2에 해당합니다.

leaq (%rse,%rsi,2), %rdx: %rsi의 값을 2배한 후 %rse에 있는 값(z)과 더한 결과를 %rdx 레지스터에 로드합니다. 이 값은 t3에 해당합니다.

salq $4, %rdx: %rdx 레지스터에 있는 값에 4를 왼쪽 시프트(shift)하여 48을 얻습니다. 이 값은 t4에 해당합니다.

leaq 4(%rdi,%rdx), %rcx: %rdi에 있는 값(x)와 %rdx에 있는 값(t4)을 더한 후 4를 더한 결과를 %rcx 레지스터에 로드합니다. 이 값은 t5에 해당합니다.

imulq %rcx, %rax: t2와 t5를 곱한 결과를 %rax 레지스터에 저장합니다. 이 값은 rval에 해당합니다.

ret: 함수에서 반환합니다.
profile
어리둥절 빙글빙글 돌아가는 코딩세상~

0개의 댓글