基本上,使用ARM汇编代码,我想加载一个具有电路板模式的文本文件。这是文本文件的样子:
704006390
000701500
000090027
002610053
400207008
610039400
930060000
006308000
048900206
(零是真实数独谜题中的空格)。我加载文本文件没有问题。我已经给出了如何检查行和列的C代码。
例如,这是检查C中的行是否正常,但我必须将其转换为arm。
int rowOK(int board[9][9], int row) {
int index;
int count[10];
for (index=0; index<10; index++)
count[index] = 0;
for (index=0; index<9; index++)
count[board[row][index]]++;
for (index=1; index<10; index++)
if (count[index] > 1)
return 0;
return 1;
}
我真正需要帮助的是如何处理这个问题。在ARM语言中,如何设置电路板以便开始检查和测试?如何将文本文件中的这些数字存储到内存中?数字应该是字符串格式还是整数?
int board[9][9]
此代码看起来像某种数组。我猜我想要制作一个阵列,但我如何在ARM中做到这一点?任何建议都表示赞赏。
答案 0 :(得分:1)
看起来你的C代码是一个二维的int数组,所以每项32位。 81个字。
想想一个字符串
char s[]="hello world";
当您单步执行该字符串中的项目
时for(i=0;s[i];s++)
您正在生成地址字符串s的基地址,以及一个偏移量,即索引号乘以每个项的大小。所以hello中的“e”是索引1,所以s +的基址(offset * size)= s_base +(1 * 1)。你只需在该地址(ldrb / strb)进行基于字节的加载或存储。
对于一个整数数组,每个32位(每个一个字)9x9是81个字。就像字符串一样,最后一个数组值一次移动一个项[a] [b]。递增b一次移动一个字(4个字节)递增a移动你最后分配的次数乘以每个的大小所以int board [d] [c]其中d和c是C中每个d增量的数字,表示c * 4字节的偏移量。
基本上是你的电路板,使用变量板[a] [b] board_base_address +(a *(9 * 4))+(b * 4)
4是2的幂,它变得容易一些board_base_address +((a * 9)&lt;&lt; 4)+(b&lt;&lt; 2)
9 = 8+1 so a*9 = a*(8+1), distribute = (a*8) + (a*1) = (a<<3) + a
所以board_base_address +(一个&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&#7)+(一个&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&quot;&#2)对于像你那样你不需要做的那个循环。
一旦你计算了地址,实现ldr或str是微不足道的。如果你对C感到满意,你可以简单地使用那个C代码并继续将它分成更小的部分,摆脱二维数组并使其成为单个板[81],你处理的是字地址而不是字节所以asm必须添加时间4.(或者如果允许的话,以字节为单位完成整个事情,你只需要数到9)。
希望你会发现无论是什么架构,x86,arm,mips等问题都是一样的。诀窍是计算地址,地址的计算是微不足道的,你只需要查找添加或编写的指令或者移动等等。只需查看简单加载或存储的指令,加载和存储就很简单。
基本上在你甚至使用汇编语言之类的东西之前做这样的事情或实际实现它
int rowOK(int board[81], int row) {
int index;
int count[10];
int boffset;
int offset;
int value;
int temp;
index=0;
do
{
count[index]=0;
index++;
}
while(index<10}
offset = row * 9;
index=0;
do
{
value=board[offset];
temp=count[value];
temp++;
count[value]=temp;
offset++;
index++;
}
while(index<9)
index=1l
do
{
temp=count[index];
if(temp>1) return(0);
}
while(index<10)
return 1;
}
任何和所有错误和拼写错误都是故意的......
然后直接敲击汇编语言要容易得多。编程至少要解决两个问题,一个是算法,两个是实现它。在这种情况下,在C中你可以使用java或pascal或python等等,然后将asm作为你想要或需要的最后一步。只需将问题分解为较小的单个步骤,直到它们类似于可以在一个或几个简单指令中完成的事情。
当然有一个叫做编译器的东西,你可以简单地编译C,输出就是汇编语言...(如果你编译成一个对象然后反汇编,就更容易阅读IMO ...)
arm-none-eabi-gcc -O2 -c myfun.c -o myfun.o
arm-none-eabi-objdump -D myfun.o
00000000 <rowOK>:
0: 27bdffd8 addiu sp,sp,-40
4: 03a01021 move v0,sp
8: 27a60028 addiu a2,sp,40
c: ac400000 sw zero,0(v0)
10: 24420004 addiu v0,v0,4
14: 1446fffd bne v0,a2,c <rowOK+0xc>
18: 00000000 nop
1c: 00051080 sll v0,a1,0x2
20: 00052940 sll a1,a1,0x5
24: 00452821 addu a1,v0,a1
28: 00852021 addu a0,a0,a1
2c: 24850024 addiu a1,a0,36
30: 8c820000 lw v0,0(a0)
34: 24840004 addiu a0,a0,4
38: 00021080 sll v0,v0,0x2
3c: 03a21021 addu v0,sp,v0
40: 8c430000 lw v1,0(v0)
44: 00000000 nop
48: 24630001 addiu v1,v1,1
4c: 1485fff8 bne a0,a1,30 <rowOK+0x30>
50: ac430000 sw v1,0(v0)
54: 27a20004 addiu v0,sp,4
58: 8c430000 lw v1,0(v0)
5c: 00000000 nop
60: 28630002 slti v1,v1,2
64: 10600006 beqz v1,80 <rowOK+0x80>
68: 24420004 addiu v0,v0,4
6c: 1446fffa bne v0,a2,58 <rowOK+0x58>
70: 00000000 nop
74: 24020001 li v0,1
78: 03e00008 jr ra
7c: 27bd0028 addiu sp,sp,40
80: 00001021 move v0,zero
84: 03e00008 jr ra
88: 27bd0028 addiu sp,sp,40
当然我不会给你手臂组装,这是mips ...当然你不应该把编译器输出作为你的任务,但是它应该让你感觉到你应该查找的指令手臂文档和如何使用它们的感觉。在这种情况下编译器正在优化不要使用优化来使程序的至少一部分类似于你应该编写的东西,可能与未经优化的代码将产生的堆栈交互较少。
您没有定义是否需要将其与C链接或只是编写一些未经测试的代码等。
答案 1 :(得分:0)
文本文件采用ascii格式。以下程序将文本文件读入内存,将每个字节放在不同的寄存器中一行。它可以以字符格式打印。要将ascii更改为整数,'Linux atoi'可以做到这一点。第一个打印行来自程序中的变量。第二行来自红色文件,索引到最后一行。
/* sudoku.s */
@ sudoku.file
@ 704006390
@ 000701500
@ 000090027
@ 002610053
@ 400207008
@ 610039400
@ 930060000
@ 006308000
@ 048900206
@ ------------------
.data
@ See /usr/include/arm-linux-gnueabihf/asm/unistd.h
@ See /usr/include/arm-linux-gnueabihf/bits/fcntl-linux.h
.equ create, 8
.equ Mode, 0644 @ -rw-r--r--
.equ open, 5
.equ Rd, 00
.equ Wr, 01
.equ RdWr, 02
.equ Apnd, 02000
.equ read, 3
.equ write, 4
.equ close, 6
.equ sync, 36
.equ exit, 1
.equ sfile, 187
.balign 4
dir_file:
.asciz "sudoku.file"
.balign 4
Open:
.word dir_file, Rd, open
.balign 4
Read:
.word Buf, 91, read
.balign 4
Buf:
.space 100
.balign 4
Row1:
.asciz "704006390"
.balign 4
Row2:
.asciz "000701500"
.balign 4
format:
.asciz " | %c %c %c | %c %c %c | %c %c %c | (num %d )\n"
.balign 4
dec_num:
.word 0
@ ------------------
.text
.global main
@ -- Subroutine -- Load registers to print --
Load_row:
ldrb r1, [r0], #1
ldrb r2, [r0], #1
ldrb r3, [r0], #1
ldrb r4, [r0], #1
ldrb r5, [r0], #1
ldrb r6, [r0], #1
ldrb r7, [r0], #1
ldrb r8, [r0], #1
ldrb r9, [r0], #1
@ ldr r0, =dec_num @ The numbers are
@ str r1, [r0] @ in ascii format.
@ push {r1-r9, lr} @ This part
@ bl atoi @ converts ascii
@ pop {r1-r9, lr} @ to integer.
mov r10, r0 @ ---- OR ----
sub r10, r1, #0x30 @ Under 10, sub hex 30
mov pc, lr
@ -- Subroutine -- Print to stdout --
Prt:
push {r0, lr}
push {r4-r10} @ The printf prints
ldr r0, =format @ r1-r3 and the
bl printf @ rest from
pop {r4-r10} @ the stack.
pop {r0, pc}
@ -- Subroutine -- Open, Read file into memory --
Rd_file:
push {r0-r12, lr}
ldr r3, =Open
ldm r3, {r0, r1, r7}
svc #0
mov r4, r0
ldr r3, =Read
ldm r3, {r1, r2, r7}
svc #0
mov r0, r4
ldr r7, =close
svc #0
pop {r0-r12, lr}
mov pc, lr
@ ---- The main program starts here ----
main:
push {r4-r10, lr}
@ ---- This is when each row is declared
@ in the .data section ----
ldr r0, =Row1
bl Load_row
bl Prt
@ ---- This is when reading the file ----
bl Rd_file
ldr r0, =Buf
add r0, #80 @ last row
bl Load_row
bl Prt
End:
pop {r4-r10, lr}
mov r0, #0
bx lr
.end
输出:
./sudoku; echo $?
| 7 0 4 | 0 0 6 | 3 9 0 | (num 7 )
| 0 4 8 | 9 0 0 | 2 0 6 | (num 0 )
0