2014-09-19 3 views
0

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

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

.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) и версия Turbo C 2,01 (TCC)

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

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

+2

Невозможно выявить какую-либо очевидную проблему. Используйте отладчик, чтобы узнать, вернется ли функция. Кроме того, расскажите своей школе, что использование таких устаревших материалов делает обучение более сложным без какой-либо выгоды. – Jester

ответ

1

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

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

ret 4 

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

В противном случае, возможно, путем изменения декларации putchar с __cdecl.

extern __cdecl void putchar(char x); 

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

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

Подробнее о calling conventions.


Примечание стороны:

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

+0

Хорошо, я попробую ваши предложения, чтобы посмотреть, как это происходит, спасибо. – goldenprize

1

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

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

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

О, и я согласен с Алексисом Вильком, смените имя.

+1

Ах! Хорошая точка зрения. Возможно, DX необходимо сохранить. Я был бы удивлен тем, что AX не будет возвратным регистром. –

+0

@AlexisWilke объявлен как пустота, и кто может когда-либо предсказать экспертов, которые делают тех компиляторов, которые намного лучше нас, глупых смертных, вы знаете? –