设置数独板

时间:2014-05-02 01:58:04

标签: assembly arm

基本上,使用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中做到这一点?任何建议都表示赞赏。

2 个答案:

答案 0 :(得分:1)

ARM与此无关。要么你了解这样的事情是如何安排在记忆中的,要么你不要。一旦你知道如何安排,那么汇编语言很容易。

看起来你的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