PintOS 2주차 - day4

솔다·2022년 12월 26일
0

오늘은 argument passing과 user memory 관련 함수를 완성했다.
argument_stack()함수를 짜기 위해서 어떻게 구성해야 하는지도 생각하기 위해 굉장히 애를 먹었는데, 동료들과 얘기해가면서 구성을 마칠 수 있었다.

void argument_stack(char **argv, int argc, struct intr_frame *if_ ){
	char *arg_addr[128];

	/*우리가 PintOS 에서 사용하는 스택은 아래로 확장하는 구조로 되어있기 때문에, 마지막 인자부터 역순으로 삽입한다.*/
	for (int i = argc -1; i >=0 ; i--){
		if_->rsp = if_->rsp - (strlen(argv[i]) + 1);
		memcpy(if_->rsp, argv[i], (strlen(argv[i]) +1 ));
		arg_addr[i] = if_->rsp;
	}

	/*word-align*/
	while (if_->rsp % 8 != 0){
		if_->rsp--;
		*(uint8_t *)if_->rsp = 0;
	}

	for (int i = argc; i>=0; i --){
		if_->rsp = if_->rsp - 8; /*8 바이트 다운*/
		if (i == argc)
		{	/*argv 가장 위에는 데이터 0 삽입*/
			memset(if_->rsp, 0, sizeof(char **));
		}
		else
		{	/*arg_addr 값 삽입, char**의 크기는 8바이트*/
			memcpy(if_->rsp, &arg_addr[i], sizeof(char **));
		}
	}

	if_->R.rdi = argc;
	/* fake return address 위의 첫번째 argv address를 가리키는 값을 저장 */
	if_->R.rsi = if_->rsp;

	/* fake address */
	if_->rsp = if_->rsp-8;	/*void pointer의 크기는 8바이트*/
	memset(if_->rsp, 0, sizeof(void *));
}

이렇게 구성하였는데, PintOS에서는 메모리영역에서 단순하게 순서대로 집어넣는게 아니라 주소값이 큰 곳에서부터 역순으로 넣는게 난관이었다. 이를 해결하기 위해서 포인터를 잘 사용해야 했다.

결국 memcpy 함수를 사용해서 넣기 때문에, 낮은 주소값을 시작값으로 넣어주는 것이 포인트였는데, for문을 돌릴때 주소값을 먼저 낮춘뒤에 memcpy 함수에 넣어주는 방법으로 해결했다.

한번 argument들을 넣는 것을 해결하고 나니, 뒤에는 똑같은 방법으로 해결할 수 있었다.

임시로 배열을 만들고 메모리에 argument 데이터를 넣을 때마다 그 포인터를 임시 배열에 넣어준 뒤에 그 배열을 새로 넣어주는 방식으로 PintOS 에서 원하는 구조로 user stack에 자료들을 넣어줄 수 있었다.

hex_dump()함수로 이 과정을 확인했을 때는 굉장히 기분이 좋았다.

처음에 유저 스택의 위치를 어디서 찾는지 고민을 하면서 코드를 여기저기 뒤져보다가 시간이 오래 걸렸는데, 나중에 intr_frame에서 rsp field가 스택의 top을 가리키는 포인터임을 파악한 뒤로는 구현이 조금 까다로웠지만 금방 해결했던 것 같다.

하지만, 아직 Project 2는 할일이 많이 남았고, 내일부터 할 일이 잔뜩 남았다. 오늘은 여기까지만 짧게 쓰고 내일부터 다시 달려볼 생각이다.

0개의 댓글