본문 바로가기

Memo

asm (생각나는 대로 정리중)

ZF, CF 등 여러 상태가 있는데 ZF는  연산 결과가 0이면 1이고 0이 아니면 0이 된다. CF는  연산 시 비트 올림이나, 비트 내림 발생 시  CF가 1로 set 됨 

  • cmp는  두 operand의 차를 사용해서 비교하는 명령어  연산 결과는 저장 안 됨 차가 0이 되면 ZF가 1로 set 됨
  • test 명령어는 두 operand AND연산하는 거임  그래서 0인지 판별할 때 많이 함 똑같이 0이면 ZF가 1로 세팅됨

cmp는  두 operand가  완전히 같은지 판단할 수 있고

test는 두 operand가  모두 0인지 판단할 수 있다. test의 경우에는  두 operand가 0이 아닌  경우를 제외하고는 값을 단정 지을 수 없기 때문에  test eax eax 같은 형태로  사용하여 값이 0이 아닌지 파악할 때 씀

위 두 개랑 jmp 계열 명령어들 같이 쓴다 예를 들어 jne 같은 경우 not equal 이니까 cmp의 값이 0이 아니었으면 ZF가 1이 아니고 둘이 다르니까 해당 레이블로 점프하지 못한다.

 

인라인 어셈블리

기본 구조는 다음과 같다 (asms : output : input : clobber);

여기서 asms는 우리가 아는 어셈블리 명령어이다 clobber는 명시되지는 않았지만 위의 명령어를 실행해  값이 변하는 것을 적어줌 

 asms 에서 $0, %1 등은 output부터 input까지 순서대로 번호가 지정돼서 들어가는 변수임

 

나머지 제약과 내용은 밑에 페이지에서 보자

출처: https://wiki.kldp.org/KoreanDoc/html/EmbeddedKernel-KLDP/app3.basic.html

 

핀토스에서 syscall 부분 예제

__attribute__((always_inline)) static __inline int64_t syscall(uint64_t num_, uint64_t a1_, uint64_t a2_,
															   uint64_t a3_, uint64_t a4_, uint64_t a5_, uint64_t a6_)
{
	int64_t ret;
	register uint64_t *num asm("rax") = (uint64_t *)num_;
	register uint64_t *a1 asm("rdi") = (uint64_t *)a1_;
	register uint64_t *a2 asm("rsi") = (uint64_t *)a2_;
	register uint64_t *a3 asm("rdx") = (uint64_t *)a3_;
	register uint64_t *a4 asm("r10") = (uint64_t *)a4_;
	register uint64_t *a5 asm("r8") = (uint64_t *)a5_;
	register uint64_t *a6 asm("r9") = (uint64_t *)a6_;
	//어셈블리코드:출력변수:입력변수:변경되는 레지스터
	//asm volatile 은 이 키워드를 사용하면 컴파일러는 프로그래머가 입력한 그래도 남겨두게 된다.
	// 즉 최적화 나 위치를 옮기는 등의 일을 하지 않는다.
	// 예를 들어 output 변수중 하나가 인라인 어셈블리엔 명시되어 있지만 다른 곳에서 사용되지 않는다고 판단되면 컴파일러는 이 변수를 알아서 잘 없애주기도 한다.
	//이런 경우 이런 것을 고려해 프로그램을 짰다면 상관 없겠지만 만에 하나 컴파일러가 자동으로 해준 일 때문에 버그가 발생할 수도 있다. 그러므로 __volatile__ 키워드를 사용해 주는 것이 좋다.
	//밑에꺼는 rax에 우리 syscall넘버를 넣어주고 나머지들도 순서에 맞게 넣어줌 그 뒤 syscall 호출해서 결과를 리턴함
	__asm __volatile(
		"mov %1, %%rax\n"
		"mov %2, %%rdi\n"
		"mov %3, %%rsi\n"
		"mov %4, %%rdx\n"
		"mov %5, %%r10\n"
		"mov %6, %%r8\n"
		"mov %7, %%r9\n"
		"syscall\n"
		: "=a"(ret)
		: "g"(num), "g"(a1), "g"(a2), "g"(a3), "g"(a4), "g"(a5), "g"(a6)
		: "cc", "memory");
	return ret;
}

num은 여기서 각 syscall 마다의 번호이다. 그게 레지스터 rax로 가고 다른 레지스터들은 추가적인 인자들

 

 

 

 

 

 

 

'Memo' 카테고리의 다른 글

서비스 계층과 도메인 서비스  (0) 2023.10.04
저장소 패턴  (0) 2023.09.29
React. UseMemo, useCallback, React.Memo  (0) 2022.01.22
TS. 덕타이핑  (0) 2022.01.21
DI? DIP  (0) 2022.01.17