<__isoc_sscanf, read_six_numbers 분석 결론>

 

Phase_2에서 read_six_numbers에 대해 분석해 얻은 결론을 떠올리면 다음과 같습니다.

 

  1. %rsi에서 전달한 문자열을 통해 __isoc99_sscanf에서 어떤 형식으로 입력을 받을지 결정할 수 있습니다. 지금 경우에는 "%d %d %d %d %d %d" 가 전달되었으므로 6개의 정수를 읽는다고 판단할 수 있습니다.
  2. 입력한 문자열이 __isoc99_sscanf 를 진행하면서 %rdi에서 전달되어 sscanf 함수를 통해 정수 배열형태로 %rsp에 저장됩니다.
  3. read_six_numbers에서 정수 배열 개수가 5개 이하라면 폭탄을 터뜨립니다.
  4. read_six_numbers는 반환값으로 입력한 정수의 개수를 반환한다. 더 자세히 말하면 read_six_numbers는가 %rax에 저장하지 않으므로,  __isoc99_sscanf 함수가 %rax에 입력한 정수의 개수를 반환합니다.

Phase_6

Dump of assembler code for function phase_6:
   0x0000555555401510 <+0>:	push   %r14
   0x0000555555401512 <+2>:	push   %r13
   0x0000555555401514 <+4>:	push   %r12
   0x0000555555401516 <+6>:	push   %rbp
   0x0000555555401517 <+7>:	push   %rbx
   0x0000555555401518 <+8>:	sub    $0x60,%rsp
   0x000055555540151c <+12>:	mov    %fs:0x28,%rax
   0x0000555555401525 <+21>:	mov    %rax,0x58(%rsp)
   0x000055555540152a <+26>:	xor    %eax,%eax
   0x000055555540152c <+28>:	mov    %rsp,%r13
   0x000055555540152f <+31>:	mov    %r13,%rsi
   0x0000555555401532 <+34>:	callq  0x555555401acc <read_six_numbers>
   0x0000555555401537 <+39>:	mov    %r13,%r12
   0x000055555540153a <+42>:	mov    $0x0,%r14d
   0x0000555555401540 <+48>:	jmp    0x555555401567 <phase_6+87>
   0x0000555555401542 <+50>:	callq  0x555555401a90 <explode_bomb>
   0x0000555555401547 <+55>:	jmp    0x555555401576 <phase_6+102>
   0x0000555555401549 <+57>:	add    $0x1,%ebx
   0x000055555540154c <+60>:	cmp    $0x5,%ebx
   0x000055555540154f <+63>:	jg     0x555555401563 <phase_6+83>
   0x0000555555401551 <+65>:	movslq %ebx,%rax
   0x0000555555401554 <+68>:	mov    (%rsp,%rax,4),%eax
   0x0000555555401557 <+71>:	cmp    %eax,0x0(%rbp)
   0x000055555540155a <+74>:	jne    0x555555401549 <phase_6+57>
   0x000055555540155c <+76>:	callq  0x555555401a90 <explode_bomb>
   0x0000555555401561 <+81>:	jmp    0x555555401549 <phase_6+57>
   0x0000555555401563 <+83>:	add    $0x4,%r13
   0x0000555555401567 <+87>:	mov    %r13,%rbp
   0x000055555540156a <+90>:	mov    0x0(%r13),%eax
   0x000055555540156e <+94>:	sub    $0x1,%eax
   0x0000555555401571 <+97>:	cmp    $0x5,%eax
   0x0000555555401574 <+100>:	ja     0x555555401542 <phase_6+50>
   0x0000555555401576 <+102>:	add    $0x1,%r14d
   0x000055555540157a <+106>:	cmp    $0x6,%r14d
   0x000055555540157e <+110>:	je     0x555555401585 <phase_6+117>
   0x0000555555401580 <+112>:	mov    %r14d,%ebx
   0x0000555555401583 <+115>:	jmp    0x555555401551 <phase_6+65>
   0x0000555555401585 <+117>:	lea    0x18(%r12),%rcx
   0x000055555540158a <+122>:	mov    $0x7,%edx
   0x000055555540158f <+127>:	mov    %edx,%eax
   0x0000555555401591 <+129>:	sub    (%r12),%eax
   0x0000555555401595 <+133>:	mov    %eax,(%r12)
   0x0000555555401599 <+137>:	add    $0x4,%r12
   0x000055555540159d <+141>:	cmp    %r12,%rcx
   0x00005555554015a0 <+144>:	jne    0x55555540158f <phase_6+127>
   0x00005555554015a2 <+146>:	mov    $0x0,%esi
   0x00005555554015a7 <+151>:	jmp    0x5555554015c3 <phase_6+179>
   0x00005555554015a9 <+153>:	mov    0x8(%rdx),%rdx
   0x00005555554015ad <+157>:	add    $0x1,%eax
   0x00005555554015b0 <+160>:	cmp    %ecx,%eax
   0x00005555554015b2 <+162>:	jne    0x5555554015a9 <phase_6+153>
   0x00005555554015b4 <+164>:	mov    %rdx,0x20(%rsp,%rsi,8)
   0x00005555554015b9 <+169>:	add    $0x1,%rsi
   0x00005555554015bd <+173>:	cmp    $0x6,%rsi
   0x00005555554015c1 <+177>:	je     0x5555554015d9 <phase_6+201>
   0x00005555554015c3 <+179>:	mov    (%rsp,%rsi,4),%ecx
   0x00005555554015c6 <+182>:	mov    $0x1,%eax
   0x00005555554015cb <+187>:	lea    0x202c5e(%rip),%rdx        # 0x555555604230 <node1>
   0x00005555554015d2 <+194>:	cmp    $0x1,%ecx
   0x00005555554015d5 <+197>:	jg     0x5555554015a9 <phase_6+153>
   0x00005555554015d7 <+199>:	jmp    0x5555554015b4 <phase_6+164>
   0x00005555554015d9 <+201>:	mov    0x20(%rsp),%rbx
   0x00005555554015de <+206>:	mov    0x28(%rsp),%rax
   0x00005555554015e3 <+211>:	mov    %rax,0x8(%rbx)
   0x00005555554015e7 <+215>:	mov    0x30(%rsp),%rdx
   0x00005555554015ec <+220>:	mov    %rdx,0x8(%rax)
   0x00005555554015f0 <+224>:	mov    0x38(%rsp),%rax
   0x00005555554015f5 <+229>:	mov    %rax,0x8(%rdx)
   0x00005555554015f9 <+233>:	mov    0x40(%rsp),%rdx
   0x00005555554015fe <+238>:	mov    %rdx,0x8(%rax)
   0x0000555555401602 <+242>:	mov    0x48(%rsp),%rax
   0x0000555555401607 <+247>:	mov    %rax,0x8(%rdx)
   0x000055555540160b <+251>:	movq   $0x0,0x8(%rax)
   0x0000555555401613 <+259>:	mov    $0x5,%ebp
   0x0000555555401618 <+264>:	jmp    0x555555401623 <phase_6+275>
   0x000055555540161a <+266>:	mov    0x8(%rbx),%rbx
   0x000055555540161e <+270>:	sub    $0x1,%ebp
   0x0000555555401621 <+273>:	je     0x555555401634 <phase_6+292>
   0x0000555555401623 <+275>:	mov    0x8(%rbx),%rax
   0x0000555555401627 <+279>:	mov    (%rax),%eax
   0x0000555555401629 <+281>:	cmp    %eax,(%rbx)
   0x000055555540162b <+283>:	jge    0x55555540161a <phase_6+266>
   0x000055555540162d <+285>:	callq  0x555555401a90 <explode_bomb>
   0x0000555555401632 <+290>:	jmp    0x55555540161a <phase_6+266>
   0x0000555555401634 <+292>:	mov    0x58(%rsp),%rax
   0x0000555555401639 <+297>:	xor    %fs:0x28,%rax
   0x0000555555401642 <+306>:	jne    0x555555401651 <phase_6+321>
   0x0000555555401644 <+308>:	add    $0x60,%rsp
   0x0000555555401648 <+312>:	pop    %rbx
   0x0000555555401649 <+313>:	pop    %rbp
   0x000055555540164a <+314>:	pop    %r12
   0x000055555540164c <+316>:	pop    %r13
   0x000055555540164e <+318>:	pop    %r14
   0x0000555555401650 <+320>:	retq
   0x0000555555401651 <+321>:	callq  0x555555400f20 <__stack_chk_fail@plt>

<+28 ~ 48>

 

   0x000055555540152c <+28>:	mov    %rsp,%r13
   0x000055555540152f <+31>:	mov    %r13,%rsi
   0x0000555555401532 <+34>:	callq  0x555555401acc <read_six_numbers>
   0x0000555555401537 <+39>:	mov    %r13,%r12
   0x000055555540153a <+42>:	mov    $0x0,%r14d
   0x0000555555401540 <+48>:	jmp    0x555555401567 <phase_6+87>

 

<+28> : %rsp는 입력한 여섯개의 정수 배열을 가리키는 포인터입니다. 이를 %r13에도 저장합니다.

 

<+31> : %rsi에도 이를 저장하지만, 테스트 결과 %rsi에 저장된 값을 read_six_numbers가 리턴되었을 때에는 이미 소멸됨을 확인했습니다.

 

<+34> : %r12에도 저장합니다.

 

<+42> : %r14d에 0을 저장합니다.

 

<+48> : <+87>로 점프합니다.

 


 

 

<+87 ~ 100> 

: %r13, %rbp가 가리키는 숫자가 1 이상 6이하인지 검사

 

   0x0000555555401567 <+87>:	mov    %r13,%rbp
   0x000055555540156a <+90>:	mov    0x0(%r13),%eax
   0x000055555540156e <+94>:	sub    $0x1,%eax
   0x0000555555401571 <+97>:	cmp    $0x5,%eax
   0x0000555555401574 <+100>:	ja     0x555555401542 <phase_6+50>

 

<+87> : %rbp에도 포인터를 넘겨줍니다.

 

 

<+90> : 입력한 첫번째 정수를 %eax에 복사합니다.

 

<+94> : %eax에서 1을 뺍니다.

 

<+97 ~ 100> : 5와 비교해서 5보다 크거나 0보다 작으면 <+50>으로 점프합니다. <+50>은 폭탄이므로 입력하는 첫번째 정수는 1 이상 6이하여야 합니다.

 

   0x0000555555401542 <+50>:	callq  0x555555401a90 <explode_bomb>

<+102 ~ 115>

: %r14d는 Outer Loop의 현재 인덱스(%r13과, %rbp가 가리키는 인덱스와 같음)

 

   0x0000555555401576 <+102>:	add    $0x1,%r14d
   0x000055555540157a <+106>:	cmp    $0x6,%r14d
   0x000055555540157e <+110>:	je     0x555555401585 <phase_6+117>
   0x0000555555401580 <+112>:	mov    %r14d,%ebx
   0x0000555555401583 <+115>:	jmp    0x555555401551 <phase_6+65>

 

<+102> : %r14d에 1을 더합니다.

 

<+106> : %r14d를 6과 비교합니다.

 

<+110> : 6과 같으면 <+117>로 점프합니다. 여기서는 점프하지 않고 넘어갑니다.

 

<+112> : %r14d의 값을 %ebx에 복사합니다.

 

<+115> : <+65>로 점프합니다.

 


<+65 ~ 76>

: %rbp가 가리키는 숫자(Outer Loop의 현재 원소)와 %eax(Inner Loop의 현재 원소)가 다른지 검사.

 

   0x0000555555401551 <+65>:	movslq %ebx,%rax
   0x0000555555401554 <+68>:	mov    (%rsp,%rax,4),%eax
   0x0000555555401557 <+71>:	cmp    %eax,0x0(%rbp)
   0x000055555540155a <+74>:	jne    0x555555401549 <phase_6+57>
   0x000055555540155c <+76>:	callq  0x555555401a90 <explode_bomb>

 

 

<+65> : %rax에 %ebx값을 복사합니다.

 

<+68> : %eax에 %rsp에서 현재 저장된 인덱스만큼 이동한 원소의 값을 저장합니다.

 

<+71> : %eax와 %rbp가 가리키는 값을 비교합니다.

 

<+74> : <+76>에서 폭탄이 터지므로 %eax와 %rbp가 가리키는 값은 달라야합니다.

 

 


 

<+57 ~ 71>

: %ebx는 Inner Loop의 인덱스

 

   0x0000555555401549 <+57>:	add    $0x1,%ebx
   0x000055555540154c <+60>:	cmp    $0x5,%ebx
   0x000055555540154f <+63>:	jg     0x555555401563 <phase_6+83>
   0x0000555555401551 <+65>:	movslq %ebx,%rax
   0x0000555555401554 <+68>:	mov    (%rsp,%rax,4),%eax
   0x0000555555401557 <+71>:	cmp    %eax,0x0(%rbp)
   0x000055555540155a <+74>:	jne    0x555555401549 <phase_6+57>
   0x000055555540155c <+76>:	callq  0x555555401a90 <explode_bomb>

 

<+57> : %ebx에 1을 더합니다.

 

<+60 ~ 63> : %ebx에 6이 되었다면 <+83>로 점프합니다.

 

<+65 ~ 71>을 수행한 후 %ebx가 6이 되기 전까지 반복합니다.


<중간결론1>

 

2중 Loop 구조입니다.

 

<+87 ~ 115> 는 Outer Loop입니다. 여기서는 %rbp, %r13을 1부터 6까지 순회합니다.(<+83>에서 오른쪽으로 한칸씩 옮겨감) 그리고 그 인덱스를 %r14d가 소유합니다.

Outer Loop를 순회하면서 각 원소마다 Inner Loop인 <+57 ~ 71>을 순회합니다.

여기서는 Outer Loop의 숫자와 Inner Loop의 숫자가 같으면 폭탄이 터지도록 합니다.

 

모든 검사가 끝나면 <+110>에서 현재 인덱스가 6인지 검사해서 순회가 끝났으므로 <+117>로 이동해 다음 과정들을 순회하게 됩니다.

 

즉, 모든 숫자는 1 이상 6 이하여야하고, 그리고 그 숫자들은 모두 달라야합니다.

 

마지막 순간에는 다음과 같은 형태가 될겁니다.

 

조건들을 만족했으니 <+117>로 가야합니다.

 


 

<+117 ~ 144, +146 ~ 151>

 

   0x0000555555401585 <+117>:	lea    0x18(%r12),%rcx
   0x000055555540158a <+122>:	mov    $0x7,%edx
   0x000055555540158f <+127>:	mov    %edx,%eax
   0x0000555555401591 <+129>:	sub    (%r12),%eax
   0x0000555555401595 <+133>:	mov    %eax,(%r12)
   0x0000555555401599 <+137>:	add    $0x4,%r12
   0x000055555540159d <+141>:	cmp    %r12,%rcx
   0x00005555554015a0 <+144>:	jne    0x55555540158f <phase_6+127>

<+117> : %rcx가 배열의 마지막 원소의 끝 주소를 가지게 합니다. (맨 마지막의 다음 숫자는 0입니다)

 

<+122 ~ 127> : %eax와 %edx에 7을 복사합니다.

 

<+129 ~ 133> : %r12가 가리키는 값을 a라고 할 때 7-a를 가지도록합니다.

 

<+141 ~ 144> : 만약 원소의 끝 주소에 도달하지 않았다면 <+117 ~ 144>를 반복합니다.

 

결론적으로, 입력한 배열의 숫자를 모두 7에서 뺀 값으로 저장하게합니다.

 

<+146 ~ 151> : 순회를 마치고, <+146>으로 진입한 후에 %esi에 0을 저장하고 <+179>로 점프합니다.

 

현재 상황은 밑과 같습니다.


 

<+179 ~ 197>

 

<+179>:	mov    (%rsp,%rsi,4),%ecx
<+182>:	mov    $0x1,%eax
<+187>:	lea    0x202c5e(%rip),%rdx        # 0x555555604230 <node1>
<+194>:	cmp    $0x1,%ecx
<+197>:	jg     0x5555554015a9 <phase_6+153>
<+199>:	jmp    0x5555554015b4 <phase_6+164>

 

<+179> : %ecx는 R[%rsi]번째 숫자가 됩니다. 지금은 0번째 인덱스 숫자인 6을 저장합니다.

 

<+182> : %eax에 1을 저장합니다.

 

<+187> : 우선은 %rdx가 0x555555604230 주소값이 저장된다고 까지만 생각하고 넘어가겠습니다.

 

<+194 ~ 197> : R[%ecx]와 1을 비교해서 1 초과라면 <+153>로 넘어가고, 1 이면 <+164>로 넘어갑니다.


 

<+153 ~ 162>

: %rdx가 node 배열의 인덱스 (R[%ecx] - 1)의 값이 가리키는 대상을 가지게 된다.

 

   0x00005555554015a9 <+153>:	mov    0x8(%rdx),%rdx
   0x00005555554015ad <+157>:	add    $0x1,%eax
   0x00005555554015b0 <+160>:	cmp    %ecx,%eax
   0x00005555554015b2 <+162>:	jne    0x5555554015a9 <phase_6+153>
(gdb) x/20xg 0x555555604230
0x555555604230 <node1>:	0x00000001000003aa	0x0000555555604240
0x555555604240 <node2>:	0x0000000200000206	0x0000555555604250
0x555555604250 <node3>:	0x0000000300000076	0x0000555555604260
0x555555604260 <node4>:	0x000000040000039c	0x0000555555604270
0x555555604270 <node5>:	0x0000000500000277	0x0000555555604110
0x555555604280 <host_table>:	0x0000555555402e47	0x0000555555402e61
0x555555604290 <host_table+16>:	0x0000555555402e7b	0x0000555555402e94
0x5555556042a0 <host_table+32>:	0x0000555555402eae	0x0000555555402ebc
0x5555556042b0 <host_table+48>:	0x0000555555402ecb	0x0000000000000000
0x5555556042c0 <host_table+64>:	0x0000000000000000	0x0000000000000000

<+153> : %rdx의 참조를 8바이트 씩 이동해서 복사하므로 보기편하도록 8바이트 배열 관점에서 관찰했습니다. 그리고 %rdx를 배열에서 한칸 옮긴 값의 참조를 저장합니다. 또한 앞으로 저 배열을 node 배열이라고 하겠습니다.

 

node 배열에서 한번 이동 : M[0x555555604230 + 0x8] 이 저장된다. 즉 0x555555604240가 저장된다.

0x555555604240 <node2>:	0x0000000200000206	0x0000555555604250

 

또한, 지금 서로의 주소값을 지니고 있는데 잘 관찰해보면 node배열은 다음과 같은 구조를 가집니다.

&node a는 노드 a의 주소값입니다.

 

 

<+157> : %eax에 1을 더합니다.

 

<+160 ~ 162> : %ecx는 R[%rsi]번째 숫자입니다. 이를 %eax와 비교해서 같을때까지 <+153 ~ 162>를 반복합니다.

 

%rsi는 0으로 고정입니다. 즉 %ecx는 0번째 숫자입니다.

또한 %eax가 1부터 %ecx가 될때까지 반복하므로, %ecx번 반복한다고 생각할 수 있고.

한번 더 나아가서, %rdx를 node 배열에서 %ecx번 이동를 반복하게 합니다.

 

예를들어, node1에서 5번 이동하면 %rdx는 node6 주소를 값으로 가집니다.

 

마지막의 상태는 다음과 같습니다.


 

 

<+164 ~ 177>

: 8바이트 단위로 옮겨서 배열이 저장되는 위치에서 0x20 떨어진곳에  %rdx가 가리키는값 저장.

 

   0x00005555554015b4 <+164>:	mov    %rdx,0x20(%rsp,%rsi,8)
   0x00005555554015b9 <+169>:	add    $0x1,%rsi
   0x00005555554015bd <+173>:	cmp    $0x6,%rsi
   0x00005555554015c1 <+177>:	je     0x5555554015d9 <phase_6+201>

 

<+164> : 우리가 입력한 배열이 저장되는 위치에서 0x20 떨어진곳에 8바이트 단위로 옮겨서 %rdx가 node 배열에 가리키는 값을 저장합니다.

 

<+169 ~ 177> : %rsi가 6이 되었다면 <+201>로 점프하고, 아니라면 <+179>에서 진행합니다.


 

<중간결론2>

 

이번에도 2중 Loop 구조입니다.

 

<+179 ~ 197> Outer Loop, <+153 ~ 177> Inner Loop 입니다.

R[%ecx]가 1이면 %rdx가 가리키는 위치를 옮길 필요가 없기때문에 <+153 ~ 162>를 진행하지 않는것 뿐이고,

결론적으로 %rdx가 가리키는 index (R[%ecx] - 1) 값을 우리가 저장한 배열 오른쪽에 저장해놓는겁니다.

 

R[%rsi] 가 가리키는 인덱스가 현재 진행하는 Outer Loop의 index입니다.

%ecx는 R[%rsi]번째 숫자만큼 이동해서 가지는 값을 0x20 + R[%rsp]부터 8바이트씩 옮겨 복사합니다.

 

즉, 1 2 3 4 5 6을 입력한 우리의 경우 배열에는 6 5 4 3 2 1( = 7-6, 7-5, 7-4, 7-3, 7-2, 7-1)이 저장되었고

그 오른쪽 주소에 %rdx가 가리키는 node배열의 node 6, node 5, node 4, node 3, node 2, node 1 의 값들이 차례대로 저장되는겁니다.

사진을 보면 다음과 같게 됩니다.

 

(배열의 주소는 보기 편하도록 한것이지, 실제 주소가 아닙니다)

 

즉, R[%rsi]가 6이 되어 Outer Loop까지 종료되었을때,

<+201> 부터 코드가 진행됩니다.


 

<+201  ~ 206> 

 

   0x00005555554015d9 <+201>:	mov    0x20(%rsp),%rbx
   0x00005555554015de <+206>:	mov    0x28(%rsp),%rax
   0x00005555554015e3 <+211>:	mov    %rax,0x8(%rbx)
   0x00005555554015e7 <+215>:	mov    0x30(%rsp),%rdx
   0x00005555554015ec <+220>:	mov    %rdx,0x8(%rax)
   0x00005555554015f0 <+224>:	mov    0x38(%rsp),%rax
   0x00005555554015f5 <+229>:	mov    %rax,0x8(%rdx)
   0x00005555554015f9 <+233>:	mov    0x40(%rsp),%rdx
   0x00005555554015fe <+238>:	mov    %rdx,0x8(%rax)
   0x0000555555401602 <+242>:	mov    0x48(%rsp),%rax
   0x0000555555401607 <+247>:	mov    %rax,0x8(%rdx)
   0x000055555540160b <+251>:	movq   $0x0,0x8(%rax)
   0x0000555555401613 <+259>:	mov    $0x5,%ebp
   0x0000555555401618 <+264>:	jmp    0x555555401623 <phase_6+275>

 

 

결론적으로 보면 기존에 오른쪽같이 연결되어있던 노드들을

위에서 0x20(%rsp)에 저장되어 있는 순서대로 재배치하는 코드입니다.

 

여기서부터는 6 3 1 2 5 4 을 입력했다고 가정하고 진행해보겠습니다.

6 3 1 2 5 4을 입력한 숫자들은 1 4 6 5 2 3 으로 변환되고, 0x20(%rsp)에 node1, node4, node6, node5, node2, node3의 주소가 배치되게 됩니다.

 

그리고 <+201  ~ 206> 을 진행하고 나면, 노드사이 관계가 오른쪽과 같이 변경됩니다.

 

변경이 완료되면 <+275>로 점프합니다.

 

 


 

<+266 ~ 285>

 

   0x000055555540161a <+266>:	mov    0x8(%rbx),%rbx
   0x000055555540161e <+270>:	sub    $0x1,%ebp
   0x0000555555401621 <+273>:	je     0x555555401634 <phase_6+292>
   0x0000555555401623 <+275>:	mov    0x8(%rbx),%rax
   0x0000555555401627 <+279>:	mov    (%rax),%eax
   0x0000555555401629 <+281>:	cmp    %eax,(%rbx)
   0x000055555540162b <+283>:	jge    0x55555540161a <phase_6+266>
   0x000055555540162d <+285>:	callq  0x555555401a90 <explode_bomb>

<+275> : %rax는 %rbx의 다음 노드 주소를 가집니다. 현재 %rbx는 첫번째 노드 주소이므로, %rax는 두번째 노드 주소입니다.

즉 R[%rbx]는 &node1, R[%rax]는 &node4 입니다.

 

<+279> : %eax는 두번째 노드인데, 그 앞의 8바이트만 가져오므로 v4를 저장합니다.

 

<+281 ~ 283> : 두번째 노드의 값인 v4와 첫번째 노드 값인 v1을 비교합니다. 그리고 v1 >= v4를 만족해야합니다. 그리고 <+266>으로 점프합니다, 아니라면 폭탄이 터집니다.

 

 

<+266> : %rbx를 다음 노드로 옮깁니다.

 

<+270 ~ 273> : %ebp를 1 감소합니다. 만약 %ebp가 0보다 작다면 <+292>로 이동합니다.

 

이를 반복하는데, 결국 %ebp가 5에서 1까지 반복하므로 총 5번 반복합니다. 그리고 %rbx를 다음 노드로 옮기면서 %eax는 %rbx의 다음 노드가 됩니다. 또한 그때마다 앞에놓인 노드의 v값이 뒤에놓인 노드의 v값보다 크거나 같아야합니다.

v값을 기준으로 내림차순을 만족해야합니다.


<결론>

 

각 노드의 v값을 나열해보면 다음과 같습니다.

 

(gdb) x/30dw 0x555555604230
0x555555604230 <node1>:	938	1	1432371776	21845
0x555555604240 <node2>:	518	2	1432371792	21845
0x555555604250 <node3>:	118	3	1432371808	21845
0x555555604260 <node4>:	924	4	1432371824	21845
0x555555604270 <node5>:	631	5	1432371472	21845

(gdb) x/1dw 0x0000555555604110
0x555555604110 <node6>:	891

 

node v node
1 938
2 518
3 118
4 924
5 631
6 891

 

노드가 큰 순서대로 나열하면

1 → 4 → 6 → 5 →2 →3

입니다.

 

그리고 이 노드들은 7에서 입력한 숫자를 뺀 값이므로,

6 3 1 2 5 4

로 변환됩니다.

 

즉 답은 다음과 같습니다.

6 3 1 2 5 4

 

 

 

'CS:APP' 카테고리의 다른 글

Pipelining의 성능 측정과 비교  (0) 2023.12.04
[CS:APP 2.2] Binary Number Encoding  (0) 2023.10.26
[CS:APP] BombLab Phase5 해설  (0) 2023.10.20
[CS:APP] BombLab Phase4 해설  (0) 2023.10.20
[CS:APP] BombLab Phase3 해설  (0) 2023.10.20

+ Recent posts