beq

beq

RISC-V 어셈블리 참조

lyszt.net은 beq 및 기타 RISC-V 명령어를 더 자세히 다룹니다.

인코딩 형식

R
31–25funct7
24–20rs2
19–15rs1
14–12funct3
11–7rd
6–0opcode
I
31–20imm[11:0]
19–15rs1
14–12funct3
11–7rd
6–0opcode
S
31–25imm[11:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:0]
6–0opcode
B
31–25imm[12,10:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:1,11]
6–0opcode
U
31–12imm[31:12]
11–7rd
6–0opcode
J
31–12imm[20,10:1,11,19:12]
11–7rd
6–0opcode

설명

beq는 프로그램이 결정을 내릴 수 있게 합니다. 프로세서는 일반적으로 명령어를 목록에 나타난 순서대로 실행합니다. 그 순서만으로는 아무것도 선택하거나 반복할 수 없습니다. 분기는 그 순서를 바꿉니다. 조건을 검사하고, 조건이 성립하면 프로세서는 다음 줄이 아닌 다른 곳에서 계속합니다. 모든 if 문과 루프는 분기로 만들어집니다.

그 다른 곳은 레이블로 이름이 붙습니다. 레이블은 이름 뒤에 콜론이 붙은 것으로 코드에서 위치를 표시합니다. 예를 들어 예제의 done 레이블과 같습니다. beq(branch if equal)는 두 레지스터를 비교합니다. 두 레지스터가 같은 값을 가지면 레이블이 표시한 위치로 점프하고, 다르면 다음 명령어로 실행이 계속됩니다. 형식은 아래에 나타나 있습니다.

beq rs1, rs2, label

beq는 다음에 실행되는 명령어만 바꿉니다. 비교의 yes 또는 no 결과를 숫자로 저장하려면 다른 명령어가 필요하며, 이는 slt 페이지에서 설명합니다.

프로세서는 프로그램 카운터라는 레지스터로 자신의 위치를 추적합니다. 이 레지스터는 실행 중인 명령어의 주소를 보유합니다. 분기가 성립하면 그 주소가 바뀌므로 다음 명령어는 레이블에서 옵니다.

RISC-V 매뉴얼은 조건 분기가 오프셋을 2바이트의 배수로 센 12비트 값으로 저장한다고 명시합니다. 오프셋은 부호 확장되어 분기 명령어의 주소에 더해지며, 플러스 마이너스 4 KiB의 범위를 제공합니다. 여기서 KiB는 1024바이트입니다. 분기 명령어는 두 레지스터를 직접 비교하고 조건 코드를 사용하지 않습니다. 매뉴얼은 그 이유로 비교와 분기를 결합한 명령어가 일반 파이프라인에 맞고 추가 상태나 임시 레지스터가 필요 없다는 점을 제시합니다. 또한 소프트웨어에게 가장 흔한 경로를 직선 코드로 유지하고, 뒤로 가는 분기는 성립하는 것으로 예측되고 앞으로 가는 분기는 성립하지 않는 것으로 예측될 것을 기대하라고 조언합니다. 적어도 처음 마주칠 때는 그렇습니다.

분기는 두 레지스터를 비교하며 명령어에 쓰인 상수를 취할 수 없으므로 beq t0, 5, label과 같은 형식은 존재하지 않습니다. 레지스터를 상수와 비교하려면 먼저 li로 상수를 레지스터에 로드한 다음 두 레지스터를 비교합니다.

li t1, 5
beq t0, t1, done

값 0은 로드할 필요가 없습니다. 레지스터 zero가 항상 그것을 보유하기 때문입니다.

흔한 사용법은 레지스터를 항상 0을 보유하는 zero와 비교하여 값이 0에 도달했는지 묻는 것입니다. 이것은 카운트다운 루프를 끝내고 결과를 확인합니다. 예제는 a0가 0까지 카운트다운했을 때 done으로 분기합니다. beq와 레이블만으로 프로그램의 모든 결정과 루프를 만들 수 있습니다.

예시

beq a0, zero, done   # if a0 == 0, jump to 'done'