2015-10-20 38 views
1

我的程序的目標是從命令行向寄存器r0傳遞一個整數的ascii字符串。 然後,我必須將ascii字符串轉換爲有符號整數並將其返回到r0,這是在atoi過程中完成的,並且它完美地工作。 然後,我必須初始化一個緩衝區,然後調用過程itoa,其中r0包含整數,r1包含緩衝區的地址。 我遇到的第一個問題,因爲我認爲有很多,我似乎無法初始化並聲明一個緩衝區,我該怎麼做?如何在ARM程序集中聲明緩衝區

這是到目前爲止我的代碼: 的.text 。全球_start .EQU退出,1 .EQU寫,4 .EQU標準輸出,1

_start: 
    ldr r5, [sp]  @argc value 
    ldr r6, =1 
    mov r8, #8   @argv address 

    ldr r4, [sp, r8]   
    add r8, r8, #4   
    mov r0, r4 
    bl atoi 
    ldr r1, =buffer 
    bl itoa 
    ldr r0, =1 
    bl println 
    mov r0, #0  @ success exit code 
    mov r7, #exit 
    svc 0   @ return to os 

atoi: 
    push {r4, lr} 
0: 
    ldrb r1, [r0], #1 
    cmp r1, #'- 
    beq 2f 
    cmp r1, #'0 
    blo 1f 
    cmp r1, #'9 
    bhi 1f 
    sub r1,r1,#'0 
    ldr r3, =0 
    mov r3,r2,lsl#3 
    add r2,r2,r2 
    add r2,r2,r3 
    add r2,r2,r1 
    bal 0b 

1: cmp r4, #1 
    rsbeq r2, r2, #0 
    mov r0, r2 
    pop {r4, pc} 

2: 
    ldr r4, =1 
    bal 0b 

itoa: 
    push {r4, r5, lr} 
    mov r4, r1 


    ldr r5, =0 
    push {r5} 
    cmp r0,#0 
    bgt 4f 

    0: ldr r5, =45 
    strb r5, [r4] , #1 
    rsb r0, r0, #0 

4: b qr10 

3: add r1, r1, #'0 
    push {r1} 
    cmp r0, #0 
    bne 4b 

1: pop {r5} 
    cmp r5, #0 
    beq 2f 
    strb r5, [r4] , #1 
    bal 1b 

2: ldr r1, =buffer 
    pop {r4,r5, pc} 



qr10: 
    mov r3, r0  @ save dividend (n) 
    ldr r1, =0x1999999a @ 2^32/10 
    sub r0, r0, r0, lsr #30 @ adjust for large dividends 
    umull r2, r0, r1, r0 @ quotient in r0 (q) 
    mov r1, r0, LSL #3 @ 8q 
    add r1, r1, r0, LSL #1 @ 10q 
    sub r1, r3, r1  @ remainder in r1 (r = n - 10q) 
    b 3b 



# determine string length 
# parameters 
# r0: address of null-terminated string 
# returns 
# r0: length of string (excluding the null byte) 
# modifies r0, r1, r2 
strlen: 
    @ push {lr} 
    mov r1, r0  @ address of string 
    mov r0, #0  @ length to return 
0: 
    ldrb r2, [r1], #1 @ get current char and advance 
    cmp r2, #0  @ are we at the end of the string? 
    addne r0, #1 
    bne 0b 
# return 
    @ pop {pc} 
    mov pc, lr  @ can do this instead of using the stack 

# write a null-terminated string followed by a newline 
# parameters 
# r0: output file descriptor 
# r1: address of string to print 
# modifies r0, r1, r2 
println: 
    push {r4, r5, r7, lr} 
# first get the string length 
    mov r4, r0  @ save the fd 
    mov r5, r1  @ and the string address 
    mov r0, r1  @ the string address 
    bl strlen  @ returns the string length in r0 
    mov r2, r0  @ put length in r2 for the WRITE syscall 
    mov r0, r4  @ restore the fd 
    mov r1, r5  @ and the string address 
    mov r7, #write 
    svc 0 
    mov r0, r4  @ retrieve the fd 
    adr r1, CR  @ get the address of the CR string 
    mov r2, #1  @ one char to write 
    mov r7, #write 
    svc 0 
    pop {r4, r5, r7, pc} @ restore registers and return to caller 

    CR: .byte '\n 
    .data 
    buffer: .space 32 
+0

我已編輯的代碼,它的工作,除了當我試圖比較r0到#0和分支到0b,如果它小於0.問題是,它始終分支,即使值132明顯大於0.任何想法爲什麼?然而,當我刪除添加的代碼,它的工作完美無瑕,添加的代碼背後的想法是支持負數... – popololvic

+0

永不知道我以前的評論,這是一個佈局問題,我發佈了適當的代碼,它的工作原理!感謝一噸 – popololvic

回答

1

編輯:分配一個緩衝區中數據段,利用空間指令:

buffer: SPACE 16 

由於空間是一個彙編程序指令,而不是CPU的命令,這可能是在你的彙編不同。

要加載地址到R1,緩衝器的地址放置到在功能結束後的代碼段的寄存器尺寸的常數,然後用LDR來加載:

mov pc, lr 
p_buffer: dcd buffer 

然後加載你需要的地方:

ldr r1, p_buffer 

現在r1包含p_buffer的內容,它是緩衝區的地址。再次,語法可能會有所不同。

+0

我不明白,你是什麼意思,當你說從SP減去所需的緩衝區大小?我也可以不使用堆棧嗎?我可以使用r1中的緩衝區地址嗎?並分配16個字節到我的緩衝區? – popololvic

+0

我看到你已經在'.data'部分有一個緩衝區 - 是你想使用的那個,並且不知道如何將它的地址加載到r1中? –

+0

是的,不知道如何分配其大小 – popololvic