Взаимодействие подпрограмм на ассемблере (x86) с языком C

У меня были некоторые проблемы, когда я пытаюсь вызвать функцию ассемблера (x86) из программы на Си.

Мой код сборки следующий:

.model small
.code 
.stack 100h
public _putchar
;---------------------
;Putchar proc
;---------------------
    _putchar proc 
        push bp
        mov bp,sp
        mov dl,[bp+4]
        mov ah,2
        int 21h
        pop bp
        ret
    _putchar endp
end

Затем я вызываю эту процедуру из C следующим образом:

extern void putchar(char x);

int main(void)
{
    putchar('x');
    return 0;
}

Чтобы скомпилировать и связать, я использую следующие командные строки (по порядку)

tcc -c -ms pchar.c
tasm putchar.asm
tlink pchar putchar, pchar 

До сих пор мы получили.obj от putchar.asm и файл.exe из ссылки на 2 файла.

Я должен также упомянуть, что мы (в классе) используем версию 2.01 турбо ассемблера (tasm) и версию 2.0 турбо ссылки (tlink) и версию 2.01 Turbo C (tcc)

Проблема возникает здесь, когда я запускаю файл.exe, я получаю вывод 'x', как и должно быть, но он застревает там, это не заканчивается.

Буду признателен за любую помощь, заранее спасибо.

2 ответа

Две возможности, которые я наблюдаю, AX а также DX может использоваться в вызывающей подпрограмме.

Я серьезно сомневаюсь, что это поможет, но попробуйте нажать и выскочить те до и после рутины.

Подтвердите или опровергните это с помощью debug. Установите точку останова, прежде чем вызывать подпрограмму, и перешагните через нее (не в нее), чтобы увидеть, хочет ли код компилятора использовать AX или же DX после вызова вашей подпрограммы ASM.

О, и я согласен с Алексис Уилк, смени имя.

Я бы сказал, может быть ret неправильно, вам может понадобиться другой тип возврата.

Возможно тот, который также удаляет параметр из стека, Паскаль, если я прав. Это было бы что-то вроде этого:

ret 4

Примечание: поскольку вы находитесь в 16 битах, это может быть ret 2 вместо ret 4, Это будет зависеть от инструкции push, используемой до all instrution.

В противном случае, возможно, изменив объявление putchar с __cdecl,

extern __cdecl void putchar(char x);

Обратите внимание на то, что в отладчике вы увидите, заботится ли о стеке по возвращении (т.е. add sp, 4 "потерять" входной параметр - поскольку вы находитесь в 16 битах, это может быть 2, а не 4.)

Я все еще удивлен, что ты использовал bp+4 и не bp+8, Вы в 16 битах, вау!

Подробнее о соглашениях о вызовах.


Примечание:

Вы можете избежать использования функции с именем putchar() поскольку он определен в стандартной библиотеке, хотя в вашем случае эта проблема, скорее всего, не затронута.

Другие вопросы по тегам