
어제 Argument_Stack에 관해서 공부하며 함수를 만들다가 함수가 잘못된 거 같아서 수정하기로 했습니다
어제 짠 함수
void argument_stack(char **argv, int argc, struct intr_frame *if_) {
char *arg_address[128]; // 인자 주소를 저장할 배열
// Part A: Word-align (단어 정렬)
for (int i = argc - 1; i >= 0; i--) {
int arg_len = strlen(argv[i]) + 1; // 인자 길이 계산
if_->rsp = if_->rsp - arg_len; // 스택 포인터 이동
memcpy(if_->rsp, argv[i], arg_len); // 인자를 스택에 복사
arg_address[i] = if_->rsp; // 인자의 주소를 배열에 저장
}
while (if_->rsp % 8 != 0) {
if_->rsp--; // 스택 포인터를 1바이트씩 이동하여 단어 정렬을 위해 0으로 채움
*(uint8_t *)if_->rsp = 0;
}
for (int i = argc; i >= 0; i--) {
if_->rsp = if_->rsp - 8; // 스택 포인터 이동
if (i == argc)
memset(if_->rsp, 0, sizeof(char **)); // 마지막 주소는 NULL로 초기화
else
memcpy(if_->rsp, &arg_address[i], sizeof(char **)); // 인자의 주소를 스택에 복사
}
if_->R.rdi = argc; // RDI 레지스터에 argc 값을 설정
if_->R.rsi = if_->rsp; // RSI 레지스터에 스택 포인터 값을 설정
if_->rsp = if_->rsp - 8; // 스택 포인터 이동
memset(if_->rsp, 0, sizeof(void *)); // 반환 주소를 NULL로 초기화
}
void argument_stack(char **argv, int argc, void **rsp) {
// command 오른쪽부터 스택에 삽입
for (int i = argc - 1; i >= 0; i--) {
int arg_len = strlen(argv[i]);
(*rsp) -= arg_len;
**(char **)rsp = argv[i];
argv[i] = *(char **)rsp; // 인자의 주소를 배열에 저장
}
while ((int)(*rsp) % 8 != 0) { //스택 포인터가 8의 배수가 되도록
(*rsp)--; // 스택 포인터를 1바이트씩 이동
**(uint8_t **)rsp = 0;
}
for (int i = argc; i >= 0; i--) {
(*rsp) -= 8; // 스택 포인터 이동
if (i == argc)
**(char ***)rsp = 0;
else
**(char ***)rsp = argv[i];
}
(*rsp) -= 8; // 스택 포인터 이동
**(void ***)rsp = 0;
}
argv 배열을 역순으로 순회하면서 각 인수를 스택에 삽입합니다. 각 인수는 rsp가 가리키는 위치에 저장됩니다. 이때 rsp는 인수의 길이(arg_len)만큼 이동합니다. 인수의 주소는 배열 argv에 저장됩니다.
스택 포인터(rsp)가 8의 배수가 되도록 조정합니다. 이를 위해 rsp가 8의 배수가 될 때까지 1바이트씩 이동하면서 0으로 초기화합니다. 이는 스택 정렬을 위해 필요한 과정입니다. 많은 아키텍처에서는 데이터에 접근할 때 정렬된 주소를 사용하는 것이 효율적이기 때문에, 스택 포인터를 8의 배수로 조정합니다.
argv 배열을 다시 역순으로 순회하면서 각 인수의 주소를 스택에 삽입합니다. 이때 rsp는 8만큼 이동합니다. 배열의 마지막 인수 다음에는 0이 저장됩니다.
스택 포인터(rsp)를 추가로 8만큼 이동시킨 후, 0을 저장합니다. 이는 스택에 인수 배열의 끝을 표시하기 위한 작업입니다.
이런 식으로 코드를 수정했는데도 잘 안돼서 printf를 써가며 디버깅하다가 도저히 몰라서 블로그를 약간 참조했습니다
입력받은 인자들을 스택에 저장하는 함수

void argument_stack(char **argv, int argc, void **rsp) {
// command 오른쪽 단어부터 스택에 삽입
for (int i = argc - 1; i >= 0; i--) {
//입력 받은 인자 1개 또한 스택에 넣어주는 것이므로 오른쪽 글자부터 넣어준다.
for (int j = strlen(argv[i]); j >= 0; j--) {
(*rsp)--; // 스택 주소 감소
**(char **)rsp = argv[i][j]; // 주소에 문자 저장
}
argv[i] = *(char **)rsp; // 인자가 스택에 저장되어있는 주소를 배열에 저장
}
while ((int)(*rsp) % 8 != 0) { //스택 포인터가 8의 배수가 되도록
(*rsp)--; // 스택 포인터를 1바이트씩 이동
**(uint8_t **)rsp = 0;
}
for (int i = argc; i >= 0; i--) {
(*rsp) -= 8;
if (i == argc) //argument의 끝을 나타내는 공백 추가
**(char ***)rsp = 0;
else // 각각의 argument가 스택에 저장되어있는 주소 저장
**(char ***)rsp = argv[i];
}
(*rsp) -= 8; //return 값의 주소인 fake address 저장
**(void ***)rsp = 0;
}

이렇게 수정하여

이렇게 Argument Parsing을 완료하였습니다
argument_stack 함수를 구현하는 과정에서 주소값에 접근하는 방법과 스택에 데이터를 저장하는 방식에 대해 이해하기 어려웠습니다. 특히, 이중 포인터와 형 변환 등의 개념이 혼동스러웠습니다. 주소값에 접근하기 위해 (char )rsp와 같은 형태로 코드를 작성하고, 스택에 데이터를 저장하기 위해 스택 포인터를 이동하면서 주소에 값을 할당하는 과정이 혼란스러웠습니다.
또한, 인자들을 스택에 역순으로 저장하는 과정과 스택 포인터를 정렬하는 과정도 이해하기 어려웠습니다. 인자의 문자를 역순으로 스택에 저장하고, 인자가 스택에 저장된 주소를 배열에 저장하는 부분도 이해가 어려웠습니다.
이러한 어려움을 해결하기 위해 여러 번의 실험과 디버깅을 통해 코드를 이해하고, 개념적인 이해를 돕는 추가적인 자료들을 찾아보는 등의 노력을 기울였습니다. 이러한 과정을 거치면서 주소값에 접근하는 방법과 스택에 데이터를 저장하는 방식에 대한 이해가 점차 높아졌고, 최종적으로 함수를 완성할 수 있었습니다.
이러한 어려움을 겪으며 코드를 구현하는 과정에서 배운 점은 노력과 탐구를 통해 어려운 개념을 이해할 수 있다는 것이었습니다. 어려움을 겪을 때는 문서나 예제 코드를 참고하고, 실험과 디버깅을 통해 코드 동작을 분석하는 등의 방법을 사용하여 문제를 해결할 수 있습니다.