2016-10-03 1 views
1

나는 정수가 저장되어있는 레지스터 $ t0를가집니다. 예를 들어 정수 1100을 저장한다고 가정 해 봅시다. 이 값의 이진 표현은 0000010001001100입니다. 물론 32 비트 레지스터의 경우 32 비트까지 확장 될 수 있지만 쉽게 수행 할 수 있습니다.레지스터 값의 각 비트를 통한 어셈블리 루프

레지스터 값의 각 비트를 반복하고 1 또는 0인지 검사하는 어셈블리에서 루프를 구현하려고합니다. 어떻게해야합니까?

아마도 등록 정보의 본질을 오해 할 것입니다. 레지스터가 32 비트 숫자를 저장한다는 것은 제 이해입니다, 네? 이는 각 비트가 특정 주소에 저장된다는 의미입니까?

나는 레지스터에 대해 shift를 사용하고 비트를 검사하려고했지만 실패했습니다. 또한 lb 명령을 살펴 보았지만 비트가 아닌 바이트가로드됩니다. 그럼 뭘 하죠?

답변

2

모든 프로세서에서 레지스터의 비트 수를 계산하는 루프를 설정합니다 (이 경우 32). 루프를 통과 할 때마다 해당 레지스터를 1로 설정 한 다음 결과를 누산기에 더합니다. 마지막으로 레지스터를 이동하십시오. 그것은 당신에게 세트 비트의 수를 제공합니다.

정확한 지침은 프로세서마다 다릅니다. 루프를 만들려면 보통 레이블을 설정하고 카운터를 줄인 다음 branch_not_equal_to zero (BNZ, BNEQ0와 비슷한 이름)와 같은 이름으로 명령어를 실행하십시오. AND는 AND, ANDI와 같은 이름을 가질 것입니다. ADD는 ADD, ADC (자리 올림으로 더하기) 일 수 있습니다. 교대는 ASR (산술 교대 권리) LSR (논리 교대 권리) 같이 무언가 일 것이다, 당신은 1 개를 교대 말하기 위하여 1 개를 통과해야 할 것입니다. 그러나 모든 프로세서는 본질적으로 이런 식으로 레지스터 비트를 읽을 수있게합니다.

+0

@Malcom McLean AND는 무엇을합니까? 편집 : 나는 질문을 편집했습니다. 나는 무엇을 부탁하려고했는데 사과하지 않는다. – user3794422

+0

두 개의 숫자를 더한다. 보통 두 개의 레지스터. –

+0

@Malcom McLean 내 의견을 편집 해주세요. – user3794422

3

몇 가지 기본 :

대부분의 (모든?) 시프트 지침은 캐리 플래그로 비트를 이동

대부분의 (모든?) CPU가 캐리 플래그가 설정의 위치로 이동, 분기 명령이

이 결합하여 다음을 수행 할 수 있습니다 :

load register1,< the value to be tested > 
load register2, 0 

Lrepeat: 
    compare register1 with 0 
    jump if zero Lexit 

    shift right register1 
    jump no carry Lskip 
    increase register2 
Lskip: 
    jump Lrepeat 

Lexit:      ; when you end up here, your register2 
          ; holds the count of bit register1 had set 

여전히 수행 할 수있는 몇 가지 최적화 :

,
Lrepeat: 
    compare register1 with 0 
    jump if zero Lexit 
    shift right register1 
    jump no carry Lskip  <-- note: here you jump ... 
    increase register2 
Lskip: 
    jump Lrepeat    <-- ... to jump again! 
Lexit: 

=====> 

Lrepeat: 
    compare register1 with 0 
    jump if zero Lexit 
    shift right register1 
    jump no carry Lrepeat  <-- so you can optimize it this way 
    increase register2 
Lskip: 
    jump Lrepeat    
Lexit: 

일부 CPU에는 "add carry"instuction이 있습니다 (예 : ). 6502 :

이 0을 추가하여, 분기 (조건 점프)를 피 (플러스 물론 수행) 각 루프 당신이 할 필요가 없습니다

shift right register1 
    add with carry register2,0 ; may look weird, but this adds a 
           ; 1 if the carry is set, which is 
           ; exactly what we want here 
    jump Lrepeat 

메모를 REGISTER2하는 데 사용할 수

ADC register,value  ; register = register + value + Carry flag 

레지스터 크기를 아십시오! 레지스터가 1이 될 때까지 반복하면 많은 시간을 절약 할 수 있습니다. 값이 0000 0000 0000 0000 0000 0001 1001

+0

MIPS를 사용하고 있습니다. 이것은 캐리 플래그가없는 것 같습니다. 권리? 또는 나는 뭔가를 놓친다. 또한 Lrepeat 루프에서 "register1을 0으로 비교"라고 말합니다. 레지스터 1에 어떤 값이 있다면 (예를 들어, 1450을 바이너리로 변환 한 경우), 레지스터는 0과 어떤 값을 비교합니까? 나는이 점을 1 점을 찾아내는 것이라고 생각하지만 그 점이 어떻게 작용할 것인가? – user3794422

+0

오, 당신이 뭔가를 섞은 것 같아요. "0이면 점프"<- 여기서 FLAG는 0입니다. Lrepeat은 값 안의 모든 1 비트가 카운트되었는지 (그리고 시프트 아웃되었는지) 확인하는 데 사용되는 레이블입니다. 이 경우 레지스터에 0이 포함되고 루프가 중지 될 수 있으므로 값이 0과 비교됩니다. – Tommylee2k

+0

MIPS에 플래그가 없습니다. 그것은 0보다 큰지와 브랜치를 비교하기 위해'BEQ reg1, reg2, target' 또는'BGEZ reg, target'과 같은 명령어를 가지고 있습니다. http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.html. 그래서 당신은 $ t0 = $ t1의 하위 비트를 설정하기 위해'andi $ t0, $ t1, 0x1'을 추측합니다. (건축 제로 레지스터가있어서'beq $ t0, $ 0, low_bit_zero' 수 있습니다) –

0

인 경우 R0으로 표시해야합니다. 예를 들어, 최하위 비트는 R0= 1011 0101입니다.

2) 두 번째 지워진 레지스터 R1=0000 0001을 사용하십시오.

3)와 R0ANDR1R0의 후 우측 시프트 R0 (따라서 다음 반복 검사 다음 비트).

4)하자 R3은 1 일 개 IFAND 연산 결과 씩 증가 (즉, 당신이) R0의 1로 실행하는 것이 세 번째 레지스터합니다. ELSE, 다시 루프하여 R0의 다음 비트를 확인하십시오.

감소 루프 카운터를 사용하여 전체 32 비트 또는 선택한 길이를 반복 할 수 있습니다.