본문 바로가기

Studying!!/공부를하자

어셈블리 Linked List Operation (insert/remove/sort/search/empty)

0. 개 관

 하나의 노드는 데이터 값과 다음 노드의 주소 값을 엔트리로 갖는다. 다음 노드의 주소 값이 -1일 경우에는 NULL을 가리키는 것으로 생각하고, 주소 값이 0일 경우에는 노드할당이 해제 혹은 초기화 된 것으로 코딩하였다.

-데이터 영역 레이블

start : 노드의 개수

start_point : 첫 노드의 주소

dArea : linked list가 저장될 영역



1. 소스 및 주석

-insert

insert

ADRr1, start;r1=address_of_start

LDRr2, [r1, #0];r2=number_of_items

CMP r2, #25;is_full?

BLEQinsert_full

CMPr2, #0;is_empty?

BEQinsert_empty

ADRr3, start_point;r3=address_of_start_point

LDRr4, [r3, #0];r4=pointer

findLastSUBSr2, r2, #1

MOVr3, r4

LDRr4, [r3, #4]!

BNEfindLast;r3=address_of_recor_last

;r4=data_of_record_last

ADDr3, r3, #8

SUBr6, r3, #4;next_address

LDRr5, [r3, #0]

SUBr3, r3, #8

CMPr5, #0;if_(next_pointer==0)_free_space

BEQcreateNode

ADRr3, dArea

ADDr3, r3, #4

findEmptyLDRr5, [r3, #0]

CMPr5, #0

ADDr3, r3, #8

BNEfindEmpty

SUBr6, r3, #4

SUBr3, r3, #8

createNodeSTRr6, [r3, #0]

STRr0, [r6, #0];store data r0

MOVr0, #-1

STRr0, [r6, #4];store next pointer

LDRr2, [r1, #0]

ADDr2, r2, #1

STRr2, [r1, #0];number increase

MOVr0, #1

Breturn0

insert_emptyADR r7, dArea;r7 =data area address

STRr0, [r7, #0]

ADRr8, start_point

STRr7, [r8, #0];start_point_address setting

ADDr5, r7, #8

MOVr8, #-1

STRr8, [r7, #4];insert_null

LDRr2, [r1, #0]

ADDr2, r2, #1

STRr2, [r1, #0];number_increase

MOVr0, #1;return_ok

Breturn0

insert_fullMOVr0, #0

Breturn0

-remove

removeADRr1, start

LDRr2, [r1, #0];r2=number_of_items

ADRr3, start_point

LDRr4, [r3, #0];r4=address_of_first_record

findItemSUBSr2, r2, #1

CMPr2, #-1

BEQnotfind_for_remove

MOVr3, r4;r3=address_of_record_first

LDRr4, [r3, #0];r4=data_of_record

CMP r0, r4

LDRr4, [r3, #4]!;r4=next_address_of_record

BEQremoving

MOVr7, r3;r7=before_address_of_record_last

BNEfindItem

removingADRr5, start_point

LDRr6, [r5, #0];r6=address_of_first_record

ADDr6, r6, #4

CMPr6, r3;r3=address_of_record

BEQremove_first

BNEremove_othrer

remove_firstSTRr4, [r5, #0]

MOVr0, #1;remove_ok

MOVr1, #0

STRr1, [r3, #0];space_free

ADRr1, start

LDRr2, [r1, #0];r2=number_of_items

SUBr2, r2, #1

STRr2, [r1, #0];decrease_number_of_item

Breturn0

remove_othrerSTRr4, [r7, #0]

MOVr0, #1;remove_ok

MOVr1, #0

STRr1, [r3, #0];space_free

ADRr1, start

LDRr2, [r1, #0];r2=number_of_items

SUBr2, r2, #1

STRr2, [r1, #0];decrease_number_of_item

Breturn0

notfind_for_remove

MOVr0, #0;remove_no

Breturn0

-sort

sortADR r1, start

LDRr2, [r1, #0];r2=number_of_items

compareADRr3, start_point

LDRr4, [r3, #0];r4=address_of_first_record

SUBSr2, r2, #1

ADDr9, r2, #1

compare0SUBSr9, r9, #1

MOVr3, r4;r3=address_of_record_first

LDRr4, [r3, #0];r4=data_of_record

CMPr9, r2

CMPNEr8, r4

LDRr5, [r3, #4]!;r5=next_address_of_record

STMFDsp!, {r0-r12, lr}

BLGTswap

LDMFDsp!, {r0-r12, lr}

SUBr7, r3, #4;r7=before_address_of_record_first

MOVr8, r4;r8=before_address_of_data

MOVr4, r5

CMPr9, #0

BNEcompare0

CMPr2, #1

BNEcompare

Breturn0

swapMOVr0, r4;r0=temp_data

SUBr1, r3, #4

STRr8, [r1, #0]

STRr0, [r7, #0]

Breturn0

-search

searchADRr1, start;r1=address_of_start

LDRr2, [r1, #0];r2=number_of_items

ADRr3, start_point;r3=address_of_start_point

LDRr4, [r3, #0];r4=pointer

findDataSUBr2, r2, #1

MOVr3, r4

LDRr4, [r3, #0];r4=data_of_record

CMPr0, r4

BEQfindIt

LDRr4, [r3, #4]!

CMPr2, #0

BNEfindData

MOVr0, #0;return_value 0

MOVpc, lr

findItMOVr0, #1;return_value 1

MOVr0, lr

STRr0, [r4, #0];store data r0

ADDr0, r4, #8

-empty

emptyADRr1, start;r1=address_of_start

LDRr2, [r1, #0];r2=number_of_items

CMPr2, #0

BEQempty_state

MOVr0, #0;return_value

MOVpc, lr

empty_stateMOVr0, #1;return_value

MOVpc, lr




2. 소스 분석

-insert

삽입부는 위의 소스에 대해 간략히 설명하면, start label에서 노드의 개수를 읽어 와서 empty상태인지 full상태인지를 확인한다.

만약 empty라면(즉, 노드의 개수가 0이라면 insert_empty라는 label로 branch한다. 여기서 dArea영역의 첫 주소 값을 읽어 와서 이 주소 값을 start_point라는 레이블이 가리키는 영역에 linked list의 첫 노드 값을 저장하고, 노드 첫 부분에서는 r0에 있는 insert하려는 값을 저장하고, 뒷부분에는 NULL값 (여기서는 -1)을 집어넣고, 1을 return한다.

만약 full인 상태인 경우는 0을 return한다.

empty도 아니고 full도 아니면 그대로 내려가 findLast 레이블에 들어가 루프를 돈다. start_point label에서 처음 주소를 읽어 와서 linked list의 루프를 돌면 r3에는 가장 마지막 노드의 뒷부분 주소, r4에는 가장 마지막 노드의 값(즉, 다음 링크의 주소인데 마지막 노드이므로 이 경우에는 NULL값인 -1)이 저장되는데, r3에서 8을 더한 값 즉, 다음 메모리 노드 영역을 탐지하여 0이면 free space이므로 그 자리에 삽입하기 위해 crateNode label 로 branch한다.

만약 다음 노드 위치가 free space가 아니라 사용 중이라면, findEmpty label로 가게 되고, 비어 있는 공간을 dArea 처음 영역부터 찾는다. 비어 있다는 것은 노드의 뒷부분이 0이면 free space 로 간주한다. (이미 앞서 full, 즉, 25개의 노드가 할당되어 있지는 않으므로 dArea영역이 끝나기 전까지 비어있는 노드를 최소한 한 개 이상은 찾을 것이다.)

삽입할 위치를 찾았으면 createNode에서 다음 주소 값(r6)을 r3에 저장된 주소 저장한다. 그리고 r6에 저장된 주소에 데이터 r0와 r6+#4의 주소에 NULL값 -1을 각각 집어넣는다. 그리고 노드의 개수 start에 1을 증가시키고 r0에 1을 저장하여 1을 return 한다.

-remove

삭제부에 대해 간략히 설명하면, start label에서 노드의 개수를 읽고, start_point label에서 첫 번째 노드 주소를 읽어온다.

그리고 루프를 돌면서 remove하려는 data가 어디에 있는지 search를 한다. 만약 돌면서 노드의 개수보다 작아질 때까지 찾지 못하면 notfind_for_remove label로 가서 0을 return 한다. search할 때에는 이전 노드와 삭제하려는 노드의 정보를 가지고 있어야 한다. 왜냐하면 삭제하려는 노드의 포인터(다음 링크 주소 값)를 이전 노드의 포인터(다음 링크 주소 값)로 옮기고, 삭제 노드의 포인터는 0으로 바꾸어줘야 한다. (이후 만약에 있을 insert시 이 위치에 새로운 노드를 생성 할 수 있게 하기 위해서)

만약 search하면 removing label로 가게 되고, 거기에서 삭제하려는 노드가 linked list의 시작 노드인지 아닌지를 compare한다.

그 결과 삭제하려는 노드가 가장 linked list의 시작노드라면 remove_first label로 간다. 그리고

start_point label의 값을 2번째 노드의 주소 값으로 바꾸고 처음 노드의 포인터(다음 링크 주소 값)를 0으로 바꾼다. start(노드의 개수) label의 값을 하나 감소하여 저장한다. 그리고 r0에 1을 저장하여 return 한다.

만약 삭제하려는 노드가 linked list의 시작 노드가 아니라면, remove_other label로 간다. 이 전 노드의 포인터(다음 링크 주소값)에 삭제하려는 노드의 포인터(다음 링크 주소값)을 저장하고, 삭제 노드의 포인터(다음 링크 주소 값)을 0으로 저장한다. start(노드의 개수) label의 값을 하나 감소하여 저장한다. 그리고 r0에 1을 저장하여 return 한다.

-sort

정렬부는 삽입 정렬을 사용하였다. 이중 루프를 돌게 하여 compare label과 그 안의 루프인 compare0을 두었다. compare0의 경우 루프 도는 회수는 compare 루프 한번 돌면 compare0가 돌아야할 루프는 하나씩 더 줄어들게 하였다. compare0는 linked list를 한번씩 compare에 정해지는 만큼 (처음 루프 수행보다 하나씩 줄어든다)까지 비교작업을 한다. 여기서 이전노드가 그 다음 노드보다 클 경우에는 swap label로 가서 두 개의 data값을 바꾼다. 그렇지 않으면 그냥 그대로 루프를 돌아 비교작업을 한다.

-search

탐색부는 시작주소부터 linked list를 읽는데 데이터 영역을 r4에 읽고 탐색하려는 값과 동일하면(r0와 비교하여) findIt label로 가서 r0를 1로 바꿔 return 시킨다.

만약 노드의 개수만큼 탐색하였는데도(즉, NULL값까지) 탐색 되지 않았다면 r0를 0으로 바꿔 return 시킨다.

-empty

empty는 start( 노드의 개수)가 0이면 1을 return 시키고, 0이 아니면 0을 return 시킨다.



1)메모리 영역



2. 첫번째 Data 삽입



3. Test1 수행 : insert(1, 3, 5, 7, 2, 4, 6)


4. Test2 수행 : remove(1, 2, 3, 4)




5. Test3 수행 : sorting 후 메모리 영역 변화(data value 변함)


6. Test4 수행 : data3 search 후 register return value



7. Test5 수행 : data 5, 6, 7 remove 후 시작주소와 노드 갯수 메모리값



8. Test6 : empty 수행 후 register return value


'Studying!! > 공부를하자' 카테고리의 다른 글

트랜지스터  (1) 2010.10.06
Pipe vs Shared Memory  (0) 2008.12.05
Linux Scheduler 분석  (0) 2008.11.17
어셈블리 strcmp_length strcmp_byte 구현  (0) 2008.10.17
Code Optimizing  (0) 2008.10.15