Проблемы с выводом на экран

Тема в разделе "WASM.OS.DEVEL", создана пользователем Lammar, 11 мар 2012.

  1. Lammar

    Lammar New Member

    Публикаций:
    0
    Регистрация:
    11 мар 2012
    Сообщения:
    2
    Пытаюсь программировать проц x86 на FASM в режиме ядра в PM, написал следующую функцию для вывода на экран:
    Код (Text):
    1. VIDEO_MEMORY_START = 0x000B8000
    2. VIDEO_MAX_X = 80
    3. VIDEO_MAX_Y = 30
    4.  
    5. ;Вывод символа на экран
    6. ; a - выводимый символ
    7. proc printChar a
    8.     ;Псевдокод:
    9.     ; [VIDEO_MEMORY_START + (VIDEO_MAX_X * y + x) * 2] = a
    10.     ; [VIDEO_MEMORY_START + (VIDEO_MAX_X * y + x) * 2 + 1] = 0x7
    11.     ;
    12.     ; x++
    13.     ;
    14.     ; if (x > VIDEO_MAX_X)
    15.     ; {
    16.     ;  x = 0
    17.     ;  y++
    18.     ; }
    19.     push eax                       ;сохраняем eax
    20.     push ebx                       ;сохраняем ebx
    21.     mov  eax,   VIDEO_MAX_X        ;eax = VIDEO_MAX_X
    22.     imul eax,   y                  ;eax = VIDEO_MAX_X * y
    23.     add  eax,   x                  ;eax = VIDEO_MAX_X * y + x
    24.     imul eax,   2                  ;eax = (VIDEO_MAX_X * y + x) * 2
    25.     add  eax,   VIDEO_MEMORY_START ;eax = VIDEO_MEMORY_START + (VIDEO_MAX_X * y + x) * 2
    26.     mov  ebx,   [a]                ;ebx = адресу, на который ссылается a
    27.     mov  [eax], ebx                ;[eax] = ebx
    28.     inc  eax                       ;eax++
    29.     mov  [eax], dword(0x7)         ;[eax] = 0x7
    30.     inc  [x]                       ;x++
    31.     cmp  [x],   VIDEO_MAX_X        ;сравниваем x и VIDEO_MAX_X
    32.     jnge .ret                      ;если x не больше или равен VIDEO_MAX_X, прыгаем на .ret
    33.     mov  [x],   0                  ;x = 0
    34.     inc  [y]                       ;y++
    35.     .ret:
    36.     pop  ebx                       ;восстанавливаем ebx
    37.     pop  eax                       ;восстанавливаем eax
    38.     ret                            ;возвращаемся
    39. endp
    40.  
    41. x db 0
    42. y db 0
    Компилируется оно нормально, запускается, но при вызове этой функции ничего не выводит. Где я тут накосячил?
    Если пишу непосредственно в видеопамять, типа:
    Код (Text):
    1.     mov eax,   0x000B8000
    2.     mov [eax], dword('T')
    3.     inc eax
    4.     mov [eax], dword(0x7)
    5.     inc eax
    6.     mov [eax], dword('e')
    7.     inc eax
    8.     mov [eax], dword(0x7)
    9.     inc eax
    10.     mov [eax], dword('s')
    11.     inc eax
    12.     mov [eax], dword(0x7)
    13.     inc eax
    14.     mov [eax], dword('t')
    15.     inc eax
    16.     mov [eax], dword(0x7)
    То всё работает.
     
  2. acckiitvar

    acckiitvar Member

    Публикаций:
    0
    Регистрация:
    26 сен 2011
    Сообщения:
    71
    А что вам мешает взять TD и проверить какой адрес у вас вычисляется? Проверьте значение сегментного регистра, оно не где не отсвечивает в коде, а должно быть 0
    И исправь еще mov [eax], dword(0x7), там же можно просто байт скопировать, зачем целый дворд?
     
  3. Lammar

    Lammar New Member

    Публикаций:
    0
    Регистрация:
    11 мар 2012
    Сообщения:
    2
    После медитаций над отладчиком и мануалами исправил
    Код (Text):
    1.     imul eax,   y                  ;eax = VIDEO_MAX_X * y
    2.     add  eax,   x                  ;eax = VIDEO_MAX_X * y + x
    на
    Код (Text):
    1.     mov  ebx,   [y]
    2.     imul eax,   ebx                ;eax = VIDEO_MAX_X * y
    3.     mov  ebx,   [x]
    4.     add  eax,   ebx                ;eax = VIDEO_MAX_X * y + x
    Заработало, выводит символы.

    И теперь у меня уже новая проблема и отладчик мне помогать не стремится. Я попытался сделать вывод строки, в цикле пробегая по её символам, пока не будет нулевой байт, и выводя их функцией выше:
    Код (Text):
    1. proc printStr s
    2.     push eax ;сохраняем eax
    3.     push ebx ;сохраняем ebx
    4.    
    5.     mov eax, 0 ;eax = 0, он будет хранить номер текущего символа для цикла
    6.    
    7.     .loop:
    8.         mov   ebx, [s]
    9.        
    10.         cmp   [ebx + eax], byte(0)
    11.         je    .loopEnd
    12.        
    13.         ccall printChar, [ebx + eax]
    14.         inc   eax
    15.         jmp   .loop
    16.    
    17.     .loopEnd:
    18.    
    19.     ccall setCursore
    20.    
    21.     pop ebx ;восстанавливаем ebx
    22.     pop eax ;восстанавливаем eax
    23.     ret
    24. endp
    И вызываю я это дело примерно так:
    Код (Text):
    1.     testStr db 'test test test', 0
    2.     ...
    3.     ccall printStr, testStr
    Если длинна строки меньше примерно 5 знаков, то всё работает, иначе оно не останавливается на нулевом байте и продолжает выводить байты программы, а дойдя до конца программы повисает. Что я делаю не так?
     
  4. valeri

    valeri New Member

    Публикаций:
    0
    Регистрация:
    3 июн 2005
    Сообщения:
    59
    Адрес:
    Russia
    У меня такое чувство, что просто значение eax либо ebx после вызова printChar портится.
    Могу ошибаться, просто я никогда с fasm не работал, в основном с masm.
     
  5. abcd008

    abcd008 New Member

    Публикаций:
    0
    Регистрация:
    8 фев 2009
    Сообщения:
    616
    а почему imul а не mul?
     
  6. acckiitvar

    acckiitvar Member

    Публикаций:
    0
    Регистрация:
    26 сен 2011
    Сообщения:
    71
    Попробуйте mov ebx, s. Вы должны адресоваться от начального адреса строки, а вы берете ее первые 4 элемента.
     
  7. FatMoon

    FatMoon New Member

    Публикаций:
    0
    Регистрация:
    28 ноя 2002
    Сообщения:
    954
    Адрес:
    Russia
    acckiitvar
    не, тут все правильно. s - это EBP+8, а - хранящийся там адрес строки, переданный в процедуру параметром

    Lammar
    Вы обе этих процедуры в какой-нибудь "хелловорлд" запихните, и вызовите. Если там где-то к видеопамяти или к портам обращаетесь, закоментируйте. Вам не результат нужен, а трассировка. Ну и в любом виндузовом отладчике погоняйте.