2010-12-27 7 views
3

안녕하세요. 하나의 plz에서 8086 어셈블리 언어로 2 차원 배열을 처리하는 방법을 알려줄 수 있습니까? 저는 어셈블리 언어 프로그래밍에서 초보자입니다. 감사합니다.어셈블리 언어의 다차원 배열

+2

"그렇다면 그것이 구부러진 기억이 아니라는 것을 알게 될 것입니다. –

답변

6

Madhur의 링크가 꽤 많이 다룹니다. 읽었습니까?

예를 들어 C 프로그래밍 수준에서 2 차원 배열을 이미 이해했다면 어셈블러는 다음 논리적 단계입니다.

예를 들어 배열 z [1] [2]는 두 번째 행의 세 번째 항목입니다. 그런 식으로 생각하면 주소가 z 플러스의 C 주소와 같습니다. 배열의 첫 번째 인덱스 시간 너비, 너비가 13 바이트이고 더하기 두 번째 인덱스라고합시다. & z + (13 * 1) +2 = & z + 15;

x86 코드가 아닌 의사 코드 사용 (숙제 인 경우). 당신이 C

 
unsigned char x[4][16]; 
unsigned char z[4][16]; 
unsigned int ra,rb; 

for(ra=0;ra<4;ra++) 
{ 
    for(rb=0;rb<16;rb++) 
    { 
     x[ra][rb]=z[ra][rb]; 
    } 
} 

에 루프가 있다면

 
;brute force 
ldr r0,=z ;load address of z into r0 
mov r1,#13 
mul r1,#1 ;make this a register or load from a memory location 
mov r2,#2 ;make this a register or load from a memory location 
add r0,r1 
add r0,r2 
ldrb r1,[r0] ;read the byte 
strb r3,[r0] ;write the byte 

;if your instruction set allows register offset 
ldr r0,=z ;load address of z into r0 
mov r1,#13 
mul r1,#1 
mov r2,#2 
add r1,r2 
ldrb r4,[r0,r1] ;read the byte 
strb r3,[r0,r1] ;write the byte 

;or immediate offset and offset is hardcoded 
ldr r0,=z ;load address of z into r0 
mov r1,#13 
mul r1,#1 
add r0,r1 
ldrb r4,[r1,#2] ;read the byte 
strb r3,[r1,#2] ;write the byte 

는 어셈블러로 변환 꽤 정직이다.

 

ldr r0,=x 
ldr r1,=z 
mov r2,#0 ;ra 
outer: 
    mov r3,#0 ;rb 
    inner: 
    mov r4,r2 lsl #2 ;16 bytes wide 
    add r4,r3 
    ldrb r5,[r1,r4] 
    strb r5,[r0,r4] 
    add r3,r3,#1 
    cmp r3,#16 
    bne inner 
    add r2,r2,#1 
    cmp r2,#4 
    bne outer 

브 루트 포스 항상 각 플랫폼 무력되는베이스 어드레스 + (시간 폭 첫번째 인덱스) + (소자의 제 인덱스 배 사이즈)에 대해 작동한다. 최적화 작업은 수행하려는 작업에 크게 의존합니다. 예를 들어 첫 번째 어셈블리 예제에서는 첫 번째 인덱스가 하드 코드 된 경우에는 1을 곱한 값을, 그렇지 않으면 # 2를 레지스터로 이동하는 바보입니다. 하드 코드 된 숫자는 2를 더하십시오. 한 번 계산하면 루프가 사용하는 레지스터의 최적 수를 변경합니다. 플랫폼에 곱셈이 없거나 아프면 가능하면 배열의 2를 2로 만듭니다. 아이디어를 얻으려면 곱셈을 없애거나 다른 트릭을 사용하면 곱셈을 제거 할 수 없으면 너비를 변경할 수 없으며 플랫폼에 영향을 미치지 않습니다.

주소가 두 레지스터의 합계 인 레지스터 오프셋 주소 지정 [r0, r1]이있는 플랫폼 예를 들어, 주소를 저장하고 기본 주소 레지스터를 파괴하지 못하게하여 다시 사용할 수 있습니다 루프. 포인터를 사용하여 포인터 스타일 (* ptr ++)을 사용하여 포인터 스타일을 사용하여 루프를 구현하는 방법을 변경할 수있는 경우 일부 플랫폼에서는 기본 레지스터를 사용하여 값을 추가 할 수 있습니다 (예 : [r0]). # 16은 r0에서 주소를 사용하고 나서 r0을 사용하여 16을 r0에 추가하면 여분의 명령어를 구울 필요가 없습니다. x86은 가지고 있다고 생각하지 않지만이 작업에 사용할 수있는 다른 기능이 있습니다.

무작위로 시작하십시오. x86 일 것입니다. 이것은 아마도 작업에 필요한 레지스터가 충분하지 않기 때문에 루프 변수를 유지하는 데 메모리를 사용해야 할 것입니다 (x86에는 많은 메모리 기반 지침이 있으므로 괜찮습니다) ,로드 및 저장 변형을 이용하여 최적화합니다.

-1
;This code grabs data bits from accumulator and outputs it to the carry 
Main: 
clr C 
mov A, #00101010b; 
call array; 
jmp Main; 
array: 
subb A, #80H; mov can work here if you did not clr C 
cpl A; check for proper array location 
mov B, #8; set division factor 
DIV AB; bit offset contained in B; 
mov R6,B; 
subb A, #30H; this bit will allow you to mov around the chosen register 
cpl A; 
mov R7, A; 
mov A, @R7; this is the array position 
inc R6; 
loop: 
rlc A; this takes the array bit to the carry for easy access 
djnz R6, loop;