здравствуйте! помогите решить проблемку. есть прога на СИ, которая будет зашиваться в ПЗУ. она должна грузиться перед запуском операционной системы(red hat). говорят, что надо что то делать со стеком и возможно что-то еще, чтоб она грузилась. объясните, пожалуйста, что и как делать!
dps86 А какие требования? Стек можно не трогать а оставить тот который есть. Только его там мало. Буквально на вызов двух трех процедур. Можешь свой задать.
Pavia, спасибо, что уделил время. собственно эта тема родилась из этой http://wasm.ru/forum/viewtopic.php?id=30733 . почитай пост в конце, пжлста
dps86 Стек можно и не троготь. А вот сегмент данных нужно настроить. Наверно лучше взять и прировнять сегменту кода.
dps86 Это делается не в си, а в ассемблере. Маленький код который настраивает си-шный код и передает ему управление. Компилируешь бинарники ассемблера и си. А после собираешь их линкером. Модель памяти tiny- код и данные будут в одном сегменте. Ты каким компилятором пользуешься?
я tasm использую. ну вот смотри например как мне сделать так чтобы заработал след пример это небоьшая прога, которая содержит сигнатуру и передаст управление на основную прогу в пзу. (ее я компилил в тасме) prg segment assume cs:prg,ds:prg,es:prg,ss:prg org 100h start: DB 55h, АAh ; загрузочная сигнатура DB 01h ; размер блока в 200h байтовых секторах jmp x_code ; передача управления нашему коду retf prg ends end start а это основная прога, в которой просто нужно ввести пароль и которая расположится по адресу x_code(ее я компилил компилятором СИ) int main() { asm{ input: ; ожидание ввода пароля ; --------------------- XOR DX,DX ; контрольная сумма enters: XOR AX,AX ; функция чтения символа с клавы INT 16h ; читаем символ CMP AL,0Dh ; это ENTER? JZ input ; если ENTER, начинаем ввод сначала XOR AH,AH ; очистить скан-код ADD DX,AX ; считаем CRC CMP DX, 'm' + 's' + 'o' JNZ enters ; если это не "mso", продолжаем ввод retf } return 0; } т.е. если все это правильно собрать в tiny, то должно работать?
не забудь, что сумма всех байтов активных блоков (размер*512), включая 55АА, должна быть равна "0", иначе биос посчитает расширение сбойным.
dps86 Так как ты не ответил на каком ты Си пишешь. Будем расматривать что на OpenWatcom. Тебе нужно написать startup на ассемблере. В котором проинициировать сегмент данных и кода. Пример можно глянуть сдесь C:\WATCOM\src\startup\dos\cstrt086.asm Набросал примерный код Код (Text): startup segment assume nothing public start extrn _Main : near ; Эта процедура ноходиться в Си. ; ROM Head db 055h, 0AAh ; Сигнатура db Len ; размер блока в 200h байтовых секторах jmp start db 001h,002h,003h,004h,005h,006h,007h,008h,009h,00Ah,00Bh, 00Ch ; Резерв 12 пользовательских переменных dw offset PIR ; Указатель на PIR структуру. start: ; Биос передает переменные ; AH - номер шины ; AL - номер функции mov cx,cs assume es:DGROUP mov es,cx ; Устанавливаем сегмент данных равным сегменту кода mov ds,cx ; Устанавливаем сегмент данных равным сегменту кода ; Настраиваем стек хотя я бы его не трогал. mov [OldSS],ss mov [OldSP],sp mov ss,cx ; Устанавливаем сегмент стека равным сегменту кода mov bx,offset DGROUP:_end ; получаем верхушку стека add bx,0Fh ; and bl,0F0h ; Выравнивание mov _STACKLOW,bx ; ... add bx,__stacksize ; устанавливаемый запрашиваемый размер стека, обычно 2КБайта mov mov sp,bx ; set sp relative to DGROUP mov _STACKTOP,bx ; set stack top call __CMain ; Вызываем код на Си. mov ss,[OldSS] mov sp,[OldSP] retf ends startup end start После компилируешь и собираешь программу.
Pavia, благодарю за помощь!!!!!!!!!!! еще пара вопросов немного переделал написаный тобой пример: startup segment assume cs:startup,ds:startup,es:startup,ss:startup ; public start extrn _Main : near ; Эта процедура ноходиться в Си. ; ROM Head db 055h, 0AAh ; Сигнатура db 1 ; размер блока в 200h байтовых секторах jmp start db 001h,002h,003h,004h,005h,006h,007h,008h,009h,00Ah,00Bh, 00Ch ; Резерв 12 пользовательских переменных ;dw offset PIR ; Указатель на PIR структуру. start: ; Биос передает переменные ; AH - номер шины ; AL - номер функции mov cx,cs ; assume esGROUP mov es,cx ; Устанавливаем сегмент данных равным сегменту кода mov ds,cx ; Устанавливаем сегмент данных равным сегменту кода call _Main ; Вызываем код на Си. input: ; ожидание ввода пароля ; --------------------- XOR DX,DX ; контрольная сумма enters: XOR AX,AX ; функция чтения символа с клавы INT 16h ; читаем символ CMP AL,0Dh ; это ENTER? JZ input ; если ENTER, начинаем ввод сначала XOR AH,AH ; очистить скан-код ADD DX,AX ; считаем CRC CMP DX, 'm' + 's' + 'o' JNZ enters ; если это не "mso", продолжаем ввод retf ends startup end start для чего нужны "Резерв 12 пользовательских переменных", Указатель на PIR структуру? тасм не понял что такое "assume esGROUP" и ругнулся. пришлось закомментить. и все заработало? нужна ли эта строка так сильно? кстати стек я решил все таки не править, как ты советовал прога на СИ выглядит так. (все эти 2 проги это только скилет, для проверки алгоритма работы) #include <conio.h> int main() { asm{ MOV AH, 02h // ; функция управления курсором MOV DX, 0202h // ; куда выводить (DH - Y, DL - X) XOR BX,BX INT 10h // ; позиционируем курсор } return 0; } собрал tlink`ом объектные файлы. создался экзешник. пробовал создать ком, нифига. не хочет. пробовал перегнать exe в com утилиотй exe2bin, тоже не работает. в итоге я решил попробовать метод "ТЫКА")) удалил PE pзаголовок hex-редактором, оставил только то что нужно, забил нулями до 200н и посчитал контр сумму. все идеално работает. можно ли так делать, я про удаление заголовка в ручную? не загнется ли прога при первом удобном случае??
dps86 Это из стандарта PCI. Это нужно компилятору что бы верно собрать файл. Хотя и без этого должно работать. Неверно. PE подразумивает 32битный код. А нужен 16 битный. То что заработало это тебе повезло. Лучше возьми 16битный компилятор си. Можно конечно и наоборот процессор перевести в защищенный режим и 32 бита но это гораздо сложнее.
16битный компилятор си. я даже не знаю какой 16битный. весь инет облазил не нашел. Borland 3.х покатит??