Вызов функции c printf из языка ассемблера ARM - PullRequest
1 голос
/ 05 ноября 2011

Мне нужно вызвать printf из рутины на ассемблере ARM. Я написал программу c, которая выполняет ту же операцию (printf("%d.%d",1,2)). Я разобрал вывод компилятора, но не очевидно, как передается строка формата. У кого-нибудь из вас есть пример кода для этого?

Вот моя тестовая процедура c, которую я использовал, чтобы понять, как вызвать printf.

 #include <stdio.h>
 #include <stdlib.h>

 int main(void) {
         printf("%d.%d\n",1,2);
         return EXIT_SUCCESS;
 }

Моя разборка основной программы выглядит следующим образом:

000081c4 <main>:
81c4:       e1a0c00d        mov     ip, sp
81c8:       e92dd800        stmdb   sp!, {fp, ip, lr, pc}
81cc:       e24cb004        sub     fp, ip, #4      ; 0x4
81d0:       e59f0014        ldr     r0, [pc, #20]   ; 81ec <.text+0x11c>
81d4:       e3a01001        mov     r1, #1  ; 0x1 
81d8:       e3a02002        mov     r2, #2  ; 0x2
81dc:       eb000212        bl      8a2c <_IO_printf>
81e0:       e3a03000        mov     r3, #0  ; 0x0
81e4:       e1a00003        mov     r0, r3
81e8:       e89da800        ldmia   sp, {fp, sp, pc}
81ec:       00060120        andeq   r0, r6, r0, lsr #2

Я вижу ветвь к процедуре _IO_printf, но не вижу, как передать ей строку формата.

Ответы [ 3 ]

2 голосов
/ 06 ноября 2011
#include <stdio.h>
#include <stdlib.h>

int main(void) {
         printf("%d.%d\n",1,2);
         return EXIT_SUCCESS;
}

компилировать и дизассемблировать:

0000842c <main>:
    842c:   e92d4008    push    {r3, lr}
    8430:   e3a01001    mov r1, #1
    8434:   e3a02002    mov r2, #2
    8438:   e59f0008    ldr r0, [pc, #8]    ; 8448 <main+0x1c>
    843c:   ebffffcc    bl  8374 <_init+0x44>
    8440:   e3a00000    mov r0, #0
    8444:   e8bd8008    pop {r3, pc}
    8448:   00008524    andeq   r8, r0, r4, lsr #10

r0 - первый параметр, строка формата, r1 - второй параметр a 1, r2 - третий параметр a 2. Строка формата - строкауказатель на массив байтов.r0 загружается с этим указателем, адресом строки байтов.В этом случае это адрес 0x8524.

, если вам интересно, вы можете посмотреть на 0x8524 и посмотреть свою строку,

8524:   252e6425    strcs   r6, [lr, #-1061]!   ; 0xfffffbdb
8528:   00000a64    andeq   r0, r0, r4, ror #20

0x25, 0x64, 0x2e, 0x25, 0x64, 0x0A,0x00

Аналогично, в вашей разборке адрес вашей строки будет

81d0:       e59f0014        ldr     r0, [pc, #20]   ; 81ec <.text+0x11c>
...
81ec:       00060120        andeq   r0, r6, r0, lsr #2

Если вы посмотрите на вашу разборку для адреса 0x60120, вы увидите свою строку.

1 голос
/ 05 ноября 2011

В C строка хранится в виде последовательности байтов.Когда вы передаете строку в функцию, вы фактически передаете адрес первого символа в строке.

Когда вы вызываете printf() (без оптимизации компилятора), аргументы помещаются в стек вобратный порядок, то есть справа налево.Затем printf() выскакивает первый аргумент, который (указатель на) строка формата.Он анализирует строку формата, чтобы определить, сколько байтов нужно извлечь для каждого последующего аргумента, и как интерпретировать их на основе типа данных (int, string и т. Д.), Которые они представляют.как уже отмечали другие, процессор ARM использует другое соглашение о вызовах.Вместо использования стека он передает первые параметры в регистрах.Но содержимое этих параметров такое же, как если бы они были переданы в стек.R0 будет содержать указатель на строку формата, и эквивалентный код, приведенный ниже, все еще точен.

Спасибо тем, кто предложил исправление.

Итак, по крайней мере, что касается printf(), ваш код эквивалентен этому:

const char formatString[] = "%d.%d";
printf(&formatString[0], 1, 2);
0 голосов
/ 06 ноября 2011

Я вижу ветвь к процедуре _IO_printf, но не вижу, как передать ей строку формата.

Почистите очки. Регистр R0 - это адрес, строка R1 - это «1», а R2 - «2». Адам Лисс не прав, в ARM вы используете R0-R4 в качестве первых 4 параметров функции.

Линия

81d0: e59f0014 ldr r0, [pc, #20] ; 81ec <.text+0x11c>

загружает этот адрес, хранящийся в «хвосте» функции после возврата в R0.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...