대부분의 컴퓨터는 8비트 바이트로 문자를 표현하며, 거의 모든 컴퓨터가 ASCII를 사용한다.
명령어 몇 개를 사용하면 워드 내의 특정 바이트를 추출할 수 있다. 그러므로 lw와 sw은 워드뿐 아니라 바이트 전송에도 충분히 사용할 수 있다. 하지만 텍스트 데이터를 다루는 프로그램이 많기 때문에 효율성을 위해서 MIPS에는 바이트 전송 명령어가 따로 있다.
- lb(load byte)
메모리에서 한 바이트를 읽어서 레지스터의 오른쪽 8비트에 채우는 명령 - sb(sotre byte)
레지스터의 오른쪽 8비트를 메모리로 보내는 명령 - lb rt, offset(rs) lh rt, offset(rs)
- Sign extend to 32 bits in rt
- lbu rt, offset(rs) lhu rt, offset(rs)
- Zero extend to 32 bits in rt
- sb rt, offset(rs) sh rt, offset(rs)
- Store just rightmost byte/halfword
문자 데이터는 보통 여러 개가 모여서 문자열(string)을 일누는데, 문자열의 길이는 가변적이다. 가변 길이의 문자열을 표시하는 방법은 세 가지가 있다.
- 문자열의 맨 앞에 길이를 표시하는 방법
- 같이 사용되는 변수에 그 길이를 표시하는 방법
- 마지막에 문자열의 끝을 표시하는 특수 문자를 두는 방법
C 언어는 문자열의 끝에 값이 0인 바이트(ASCII의 null) 하나를 두는 세 번째 방법을 사용한다.
String Copy Procedure Example
strcpy는 문자열을 복사하는 프로시저로, C 언어의 관례에 따라 null 바이트로 끝나는 방식을 사용한다.
void strcpy (char x[], char y[]){
int i;
i = 0;
while ((x[i] = y[i]) != ‘\0’) /* copy & test byte */
i += 1;
}
- Addresses of x, y in $a0, $a1
- i in $s0
이 프로시저의 MIPS 어셈블리 코드를 보여라.
strcpy는 먼저 스택 포인터를 조정하고 $s0를 스택에 넣는다.
strcpy:
addi $sp, $sp, -4 # adjust stack for 1 more item
sw $s0, 4($sp) # save $s0
다음은 i를 0으로 초기화하기 위해 $s0에 0을 넣는 일이다. 이 일은 0에 0을 더해서 $s0에 넣는 명령어로 처리한다.
add $s0, $zero, $zero # i = 0 + 0
다음은 반복문의 시작이다. 먼저 y[]에 i를 더해서 y[i]의 주소를 계산한다.
L1: add $t1, $s0, $a1 # address of y[i] in $t1
y는 워드 배열이 아니고 바이트 배열이므로 i에 4를 곱할 필요는 없음에 주의해야 한다.
y[i]에 문자를 load하려면, lub를 사용하여 문자를 $t2에 넣는다.
lbu $t2, 0($t1) # $t2 = y[i]
같은 방식으로 주소를 계산하여 x[i]의 주소를 $t3에 넣은 후, 이 주소를 이용하여 $t2에 있는 글자를 x[i]에 넣는다.
add $t3, $s0, $a0 # address of x[i] in $t3
sb $t2, 0($t3) # x[i] = y[i]
복사한 문자가 0(null)이면, 즉 문자열의 마지막 바이트이면 반복문을 종료한다.
beq $t2, $zero, L2 # if y[i] == 0, go to L2
0(null)이 아니면 i를 증가시키고 다시 반복한다.
addi $s0, $s0, 1 # i = i + 1
j L1 # go to L1
반복문의 처음으로 가지 않았다면, 문자열의 마지막 바이트를 만난 것이다.
$s0와 스택 포인터를 복구하고 되돌아간다.
L2: lw $s0, 0($sp) # y[i] == 0: end of string;
# restore old $s0
addi $sp, $sp, 4 # pop 1 word off stack
jr $ra # return
C에서 i에 대한 연산을 피하기 위해 보통은 배열 대신 포인터를 사용한다.
strcpy:
addi $sp, $sp, -4 # adjust stack for 1 more item
sw $s0, 4($sp) # save $s0
add $s0, $zero, $zero # i = 0 + 0
L1: add $t1, $s0, $a1 # address of y[i] in $t1
lbu $t2, 0($t1) # $t2 = y[i]
add $t3, $s0, $a0 # address of x[i] in $t3
sb $t2, 0($t3) # x[i] = y[i]
beq $t2, $zero, L2 # if y[i] == 0, go to L2
addi $s0, $s0, 1 # i = i + 1
j L1 # go to L1
L2: lw $s0, 0($sp) # y[i] == 0: end of string;
# restore old $s0
addi $sp, $sp, 4 # pop 1 word off stack
jr $ra # return