어셈블리 strcmp_length strcmp_byte 구현
strcmp_length.s 경우:
문자열 길이로 비교.
문자열의 길이가 같고, 1byte당 값도 같으면 0 return.
문자열의 길이가 다르고 test code상의 변수 in1이 길면 1 return, 더 짧으면 -1 return.
만약 문자열의 길이가 같고, 1byte당 값이 다를 경우 앞에서부터 차이가 나는 순간의 in1와 int2의 해당 byte값을 비교하여 in1의 값이 더 크면 1 return. 더 작으면 -1 return.
strcmp_byte.s 경우:
바이트코드(아스키코드) 크기 비교(일반적인 C언어에서 사용하는 strcmp() 함수와 동일)
앞에서부터 char 1byte씩 비교 후 다르다면, 거기서 멈추고 return. 이 때 return값은 test code상의 변수인 in1-in2 return. (즉, 앞 char 아스키코드 - 뒤 char 아스키코드 값)
문자열의 길이가 같고 byte당 값이 같다면 역시 in1-in2 return (즉, 0 return)
1. 소스코드
-strcmp_byte.s
AREA |.text|, CODE, READONLY
EXPORT strcmp_byte
strcmp_byte
LDRB r2,[r0],#1 ;parameter r0주소의 in1을 byte단위로 r2에 load
LDRB r3,[r1],#1 ;parameter r1주소의 in1을 byte단위로 r3에 load
CMP r2,r3
BNE return3 ;r2와 r3가 동일한 값 가지지 않으면 return으로 branch
CMP r2,#0
BEQ return3 ;r2가 0이면(즉, r2의 값이 더 없으면) return으로 branch
B strcmp_byte
return3
SUB r0, r2, r3 ;r2-r3의 결과 값을 return(바이트 크기 비교)
MOV pc,lr
END
-strcmp_length.s
AREA |.text|, CODE, READONLY
EXPORT strcmp_length
strcmp_length
MOV r4, #0
MOV r5, #0
LDRB r2,[r0],#1 ;parameter r0주소의 in1을 byte단위로 load
LDRB r3,[r1],#1 ;parameter r0주소의 in2을 byte단위로 load
CMP r2, r3
MOVGT r5, #1 ;r2와 r3이 동일 값 아니면 1 저장
MOVLT r5, #-1 ;r2와 r3이 동일 값 아니면 -1 저장
CMP r4, #0
MOVEQ r4, r5 ;r4가 0일 때만 r5값 저장
CMP r2, #0
BEQ return1
CMP r3, #0
BEQ return2
B strcmp_length_loop
return1 ;r2와 0이 같을 경우(즉, r2값이 더 이상 없을 때)
CMP r3, #0
MOVNE r0, #-1 ;r3가 더남아있으므로 -1 리턴
MOVEQ r0, r4 ;r3도 더 남아있지 않다면, r4값 리턴(최상위 byte 차이기준)
MOV pc,lr
return2 ;r3와 0이 같을 경우(즉, r3값 더이상 없고, r2값 남았을때)
MOV r0, #1
MOV pc,lr
END
2.소스코드설명
-strcmp_length.s
1. 처음에 r4와 r5에 각각 0을 저장한다.
2. 스트링의 길이를 비교하는 함수는 먼저 레지스터 r0, r1에 저장되어 있는 메모리의 주소 값에서 r2, r3로 각각 load하고나서, 1을 더한다. (post-indexing방식)
3. r2와 r3값을 비교하여 만약 다르다면 r5에 그 값을 저장한다. 그리고 r4가 0이라면 r5값을 r4에 넘긴다.(즉, r4는 최초 한번 값을 받거나 아니면 영원히 0이다.) 이는 후에 두 스트링 type의 input이 만약 동일한 길이라면, 이 앞에서부터 기준으로 차이가 났을 때 값에 따른 strcmp_lenth결과를 출력하게 하기 위해서이다.
4. r2와 0을 비교하여 r2의 값이 더 남아 있는지 없는지 확인하고, 0이라면(r2값이 더 남아있지 않다면, return1로 branch 한다. 그리고 label return1에서 r3와 0을 비교하여 r3값이 더 남아있는지 확인 후에 더 남아있으면 뒤의 값이 더 길다는 의미므로 -1을 return. r3값이 더 남아있지 않다면 저장해둔 r4값을 return한다.
5. r2와 0을 비교하고 더 남아있다면 r3와 0을 비교한다. 만약 r3값이 더 남아있지 않다면 label return2로 가서 무조건 1을 return한다.(왜냐하면 전 명령에서 r2는 남아있다는 것을 알기 때문이다) 만약 r3값이 더 남아있다면, loop를 돈다.
-strcmp_byte.s
처음은 동일하다.
1. 스트링의 길이를 비교하는 함수는 먼저 레지스터 r0, r1에 저장되어 있는 메모리의 주소 값에서 r2, r3로 각각 load하고나서, 1을 더한다. (post-indexing방식)
2. r2와 r3값을 비교하여 만약 다르다면 label return3로 바로 branch하고, r2-r3값을 return 한다.
3. r2와 r3값이 만약 같다면, r2값과 0을 비교한다. 이는 r2값이 더 이상 값이 남아있는지 없는지 아닌지를 알기 위해서이다. 여기서 더 이상 없다면, return3로 branch 한다. 그리고 r2-r3값을 return 한다.(r3값은 따로 비교할 필요가 없다. r2보다 짧다면, 2번에서 먼저 branch 했을 것이고, r2와 동일하다면, 역시 0을 return 할 것이다. r2보다 더 길다면, 0-해당r3byte를 하여 음수 값을 return 할 것이다.)
4. 2, 3번에서 branch 하지 않았다면 loop를 돈다.
-test_strcmp.c
1. extern int strcmp_byte(char *a, char *b); 선언
extern int strcmp_length(char *a, char *b); 선언
2. ret_byte는 strcmp_byte()의 return 값이고, ret_length는 strcmp는 strcmp_length() return 값이다. 둘다 int type이다. input이 되랴 스트링 변수 in1, in2를 선언한다.(char in1[], in2[];) 각각에 비교할 string를 초기 값으로 넣고 test한다.
3. 처음 byte단위 문자열 비교함수에 들어가 return하고, 다음 length 기준으로 문자열 비교함수에 들어가 return 한다. 각각의 경우 후에 printf함수를 이용해 return 값을 출력한다.