Взаимодействие подпрограмм на ассемблере (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()
поскольку он определен в стандартной библиотеке, хотя в вашем случае эта проблема, скорее всего, не затронута.