Пытаюсь программировать проц x86 на FASM в режиме ядра в PM, написал следующую функцию для вывода на экран: Код (Text): VIDEO_MEMORY_START = 0x000B8000 VIDEO_MAX_X = 80 VIDEO_MAX_Y = 30 ;Вывод символа на экран ; a - выводимый символ proc printChar a ;Псевдокод: ; [VIDEO_MEMORY_START + (VIDEO_MAX_X * y + x) * 2] = a ; [VIDEO_MEMORY_START + (VIDEO_MAX_X * y + x) * 2 + 1] = 0x7 ; ; x++ ; ; if (x > VIDEO_MAX_X) ; { ; x = 0 ; y++ ; } push eax ;сохраняем eax push ebx ;сохраняем ebx mov eax, VIDEO_MAX_X ;eax = VIDEO_MAX_X imul eax, y ;eax = VIDEO_MAX_X * y add eax, x ;eax = VIDEO_MAX_X * y + x imul eax, 2 ;eax = (VIDEO_MAX_X * y + x) * 2 add eax, VIDEO_MEMORY_START ;eax = VIDEO_MEMORY_START + (VIDEO_MAX_X * y + x) * 2 mov ebx, [a] ;ebx = адресу, на который ссылается a mov [eax], ebx ;[eax] = ebx inc eax ;eax++ mov [eax], dword(0x7) ;[eax] = 0x7 inc [x] ;x++ cmp [x], VIDEO_MAX_X ;сравниваем x и VIDEO_MAX_X jnge .ret ;если x не больше или равен VIDEO_MAX_X, прыгаем на .ret mov [x], 0 ;x = 0 inc [y] ;y++ .ret: pop ebx ;восстанавливаем ebx pop eax ;восстанавливаем eax ret ;возвращаемся endp x db 0 y db 0 Компилируется оно нормально, запускается, но при вызове этой функции ничего не выводит. Где я тут накосячил? Если пишу непосредственно в видеопамять, типа: Код (Text): mov eax, 0x000B8000 mov [eax], dword('T') inc eax mov [eax], dword(0x7) inc eax mov [eax], dword('e') inc eax mov [eax], dword(0x7) inc eax mov [eax], dword('s') inc eax mov [eax], dword(0x7) inc eax mov [eax], dword('t') inc eax mov [eax], dword(0x7) То всё работает.
А что вам мешает взять TD и проверить какой адрес у вас вычисляется? Проверьте значение сегментного регистра, оно не где не отсвечивает в коде, а должно быть 0 И исправь еще mov [eax], dword(0x7), там же можно просто байт скопировать, зачем целый дворд?
После медитаций над отладчиком и мануалами исправил Код (Text): imul eax, y ;eax = VIDEO_MAX_X * y add eax, x ;eax = VIDEO_MAX_X * y + x на Код (Text): mov ebx, [y] imul eax, ebx ;eax = VIDEO_MAX_X * y mov ebx, [x] add eax, ebx ;eax = VIDEO_MAX_X * y + x Заработало, выводит символы. И теперь у меня уже новая проблема и отладчик мне помогать не стремится. Я попытался сделать вывод строки, в цикле пробегая по её символам, пока не будет нулевой байт, и выводя их функцией выше: Код (Text): proc printStr s push eax ;сохраняем eax push ebx ;сохраняем ebx mov eax, 0 ;eax = 0, он будет хранить номер текущего символа для цикла .loop: mov ebx, [s] cmp [ebx + eax], byte(0) je .loopEnd ccall printChar, [ebx + eax] inc eax jmp .loop .loopEnd: ccall setCursore pop ebx ;восстанавливаем ebx pop eax ;восстанавливаем eax ret endp И вызываю я это дело примерно так: Код (Text): testStr db 'test test test', 0 ... ccall printStr, testStr Если длинна строки меньше примерно 5 знаков, то всё работает, иначе оно не останавливается на нулевом байте и продолжает выводить байты программы, а дойдя до конца программы повисает. Что я делаю не так?
У меня такое чувство, что просто значение eax либо ebx после вызова printChar портится. Могу ошибаться, просто я никогда с fasm не работал, в основном с masm.
Попробуйте mov ebx, s. Вы должны адресоваться от начального адреса строки, а вы берете ее первые 4 элемента.
acckiitvar не, тут все правильно. s - это EBP+8, а - хранящийся там адрес строки, переданный в процедуру параметром Lammar Вы обе этих процедуры в какой-нибудь "хелловорлд" запихните, и вызовите. Если там где-то к видеопамяти или к портам обращаетесь, закоментируйте. Вам не результат нужен, а трассировка. Ну и в любом виндузовом отладчике погоняйте.