Форум программистов, компьютерный форум, киберфорум
ОС на Assembler
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.54/13: Рейтинг темы: голосов - 13, средняя оценка - 4.54
2 / 2 / 1
Регистрация: 24.03.2015
Сообщений: 13

Некорректный вывод BMP - VESA

20.06.2015, 21:22. Показов 2587. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте!

Есть проблема. Пытаюсь вывести BMP картинку(24bpp) в режиме VESA(1024x768x24). Написал процедуру, все вроде как работает(я еще не реализовал обратный вывод байтов по этому картинка перевернутая):


Но! Если размеры выводимой картинки больше 80px. - то получается непонятно что:

Название: bad2.jpg
Просмотров: 80

Размер: 9.8 Кб

Проверял в Bochs, QEMU и VMware, результат везде одинаков.

Кто знает, подскажите пожалуйста как исправить
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
;*******************************************
;* Вывод BMP(24bpp) - режим VESA 1024x768x24
;*******************************************
xor ebx,ebx ;счетчик строк
 
mov esi,BMPSTART+54                ;в ESI - адрес начала палитры bmp
mov edi,dword[LINEAR_FRAME_BUFFER] ;в EDI - адрес начала LFB
 
new_line:
        inc ebx     ;начинаем с новой строки
        xor ecx,ecx ;обнуляем для нее счетчик столбцов
 
        line_out:
                inc ecx ;начинаем с нового столбика
 
                        ;считываем RGB составляющие и записываем их в LFB
                        ;сделал за три захода для наглядности
                        mov al,byte[esi]
                        mov byte[edi],al
                        inc edi
                        inc esi
 
                        mov al,byte[esi]
                        mov byte[edi],al
                        inc edi
                        inc esi
 
                        mov al,byte[esi]
                        mov byte[edi],al
                        inc edi
                        inc esi
 
                        cmp ecx,80   ;если строку вывели не полностью
                        jne line_out ;продолжаем выводить
 
                cmp ebx,80  ;если все строки рисунка вывели
                je  bmp_out ;на выход :)
 
                ;а если не все - рассчитываем смещение следующей строки
                mov eax,ebx            ;в eax - номер строки
                mov edx,X_RESOLUTION*3 ;в edx - длина строки в байтах
                mul edx                ;X_RESOLUTION*3*ebx - смещение начала новой строки
 
                mov edi,dword[LINEAR_FRAME_BUFFER] ;в EDI - адрес начала LFB
                add edi,eax ;добавляем смещение
 
                jmp new_line ;и продолжаем уже с новой строки
bmp_out:
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
20.06.2015, 21:22
Ответы с готовыми решениями:

Вывод точки на экран в VESA-режимах
Здравствуйте, уважаемые коллеги. Я в программировании далеко не начинающий, и честно говоря немного смущен необходимостью обращаться к...

Некорректный вывод массива
Здравствуйте, написал код для ввода массива из 25 элементов и данный массив должен выводиться 5х5. Проблема в том что он как то странно...

Некорректный вывод в массив Assembler
Код, который в матрице 4на3 в 1 строке считает среднее арифметическое элементов во 2 строке просто сумму элементов и в 3 строке снова ср...

14
8 / 8 / 5
Регистрация: 28.03.2014
Сообщений: 137
20.06.2015, 22:02
Лучший ответ Сообщение было отмечено Taatshi как решение

Решение

Я писал свою ос (уже написал, сейчас пишу другую) и вот так я выводил bmp 24 bit.

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
struc BMPHeader
{
    .sibnature dw ? ;4D42h
    .size dd ?
    .rsvd1 dw ?
    .rsvd2 dw ?
    .poff dd ?;36h
    .psize dd ?;28h
    .x dd ?
    .y dd ?
    .bplosk dw ?;1
    .bpp dw ?;24
    .method dd ?;0
    .gsize dd ?
    .xm dd ?
    .ym dd ?
    .colour dd ?;0
    .mc dd ?;0
}
virtual at 0
BMPHeader BMPHeader
end virtual
 
draw_bmp: ;stdcall draw_bmp, x, y, mem
    pushad
 
    mov   eax, dword [ds:esp+(20h+4)]
    mov   ebx, dword [ds:esp+(20h+8)]
    mov   edi, dword [ds:esp+(20h+12)]
    mov   [draw_bmp.x], eax
    mov   [draw_bmp.y], ebx
    mov   [draw_bmp.address], edi
 
    mov   eax, dword [edi+12h]
    mov   ebx, dword [edi+16h]
    mov   [draw_bmp.xi], eax
    mov   [draw_bmp.yi], ebx
 
 
    mov   edi, [draw_bmp.address]
    add   edi, [edi+BMPHeader.poff]
 
    mov   eax, [draw_bmp.x]
    mov   ebx, [draw_bmp.y]
    add   ebx, [draw_bmp.yi]
 
    mov   ecx, [draw_bmp.yi]
    draw_bmp.draw_y:
      push  ecx
      mov   ecx, [draw_bmp.xi]
      mov   eax, [draw_bmp.x]
        draw_bmp.draw_x:
 
          call  get_color_bmp_rbg
 
          call  save_pixel
 
          inc   eax
          add   edi, 3
 
          dec   ecx
          jnz   draw_bmp.draw_x
      dec   ebx
      pop   ecx
      dec   ecx
      jnz   draw_bmp.draw_y
 
    popad
    ret 12
 
 
    draw_bmp.x dd 0
    draw_bmp.y dd 0
    draw_bmp.xi dd 0
    draw_bmp.yi dd 0
    draw_bmp.address dd 0
 
get_color_bmp_rbg:
          mov   edx, 0
          mov   dl, byte [ds:edi+02h]
          shl   edx, 10h
          mov   dh, byte [ds:edi+01h]
          mov   dl, byte [ds:edi+00h]
          ret
Добавлено через 1 минуту
mem - адрес загруженного изображения.

Добавлено через 2 минуты
надо получать параметры изображения, а не выводить с заданными параметрами

Добавлено через 2 минуты
И еще 24 бита на пиксель это плохо. будет медленно выводится. я тоже мучался (окна очень медленно выводились, курсор) просто изменил на 32 ok.
0
2 / 2 / 1
Регистрация: 24.03.2015
Сообщений: 13
20.06.2015, 23:28  [ТС]
Спасибо за быстрый ответ!

По поводу замечаний согласен:
Цитата Сообщение от Вадик_ Посмотреть сообщение
надо получать параметры изображения, а не выводить с заданными параметрами
реализовал с заданными параметрами для упрощения кода, затем планировал нормально переписать.

Цитата Сообщение от Вадик_ Посмотреть сообщение
24 бита на пиксель это плохо...
сделал для удобства(24 бит режим VESA/24 бит BMP).

За код спасибо, но кажется он мне мало поможет: не могу понять, где у вас находится адрес LFB, что делает процедура get_color_bmp_rbg, для чего нужны draw_bmp.xi и draw_bmp.yi, что должна делать процедура save_pixel...

В общем завал...
0
8 / 8 / 5
Регистрация: 28.03.2014
Сообщений: 137
21.06.2015, 21:17
Лучший ответ Сообщение было отмечено Taatshi как решение

Решение

xi - размер по x
yi - размер по y

get_color_bmp_rbg - получает цвет (edi - адрес пикселя в изображении bmp) выдаёт цвет в формате gbr(вроде) в регистре edx. это для функции вывода пикселя на экран.

save_pixel = draw_pixel

Добавлено через 4 минуты
а вот код save_pixel

Assembler
1
2
3
4
5
6
7
8
9
10
save_pixel:
    pushad
    mov   esi, [REDRAW_ADDRESS]
    imul  ebx, 800
    add   ebx, eax
    shl   ebx, 2
    add   esi, ebx
    mov   dword [ds:esi], edx
    popad
    ret
он сохранял цвет пикселя во временный буффер. когда отрисовка заканчивается, данные из буффера копируются в lfb

но можно REDRAW_ADDRESS заменить на адрес LFB.

Добавлено через 39 секунд
это код из оболочки
0
3 / 3 / 0
Регистрация: 21.03.2015
Сообщений: 26
01.01.2016, 21:29
Я конечно не вовремя, но всё же.
Кажется, вы не учли, что в формате bmp24 есть выравнивание по 4 байтам в каждой строке изображения.

Пример:
Ширина картинки у вас 25 пикселей.
Каждый пиксель у вас кодируется 3 байтами.
25 * 3 = 75 байт
75 не делится нацело на 4.
И формат будет добавлять в конце строки несколько байт (в данном случае 3), чтобы добиться выравнивания. Эти байты учитывать и выводить не нужно.

Когда у вас ширина 80 пикселей, то лишних байтов нет - 80*3 = 240. 240 делится нацело на 4.

Кстати, при использовании bmp 32 бита, а не 24 такой проблемы не будет, так как каждый пиксель кодируется 4 байтами.
1
04.01.2016, 22:39

Не по теме:

Цитата Сообщение от Вадик_ Посмотреть сообщение
Я писал свою ос (уже написал, сейчас пишу другую)
Вы меня конечно извините, но :rofl:

0
8 / 8 / 5
Регистрация: 28.03.2014
Сообщений: 137
05.01.2016, 00:52
Прошлая была почти полностью на асме, а эта на СИ. Но архитектура похожая.
0
2 / 2 / 1
Регистрация: 24.03.2015
Сообщений: 13
06.01.2016, 17:28  [ТС]
Спасибо за ответ Nola, но кажется это не то.

Только что проверил при размерах BMP 79х79 - все нормально отображается!
0
3 / 3 / 0
Регистрация: 21.03.2015
Сообщений: 26
07.01.2016, 00:58
А при ширине 78 или 77?
При 79 у нас получается 3 байта выравнивания, то есть один целый лишний пиксель. И скорее всего вы его просто не выводите, т.к. размер картинки меньше, либо с самого края у вас должна быть полосочка.
А вот при 78 будет два байта выравнивания, а значит программа считает их и 1 байт со следующего пикселя и начнётся сдвиг картинки и полоски цвета. С 77 похожая ситуация.
2
1378 / 522 / 72
Регистрация: 21.07.2015
Сообщений: 1,308
07.01.2016, 01:50
Pycik, Nola прав: в bmp количество пикселей строке всегда кратно 4м ("лишние" просто не должны отображаться). Ну и сама картинка в файле зеркально отражена снизу вверх. Т. е. в видеопамять выводи задом наперед (последняя строка из фала должна быть самой верхней в видеопамяти).
1
2 / 2 / 1
Регистрация: 24.03.2015
Сообщений: 13
10.01.2016, 22:18  [ТС]
Огромное спасибо Nola, shmkv!

Создал BMP размером 3x3x24bit:
https://www.cyberforum.ru/atta... 1452453465

и открыл в hex-редакторе:
https://www.cyberforum.ru/atta... 1452453465

сразу все понятно

Разноцветные прямоугольники это составляющие RGB, а жирные чёрные - байты для выравнивания. Я это не учёл и вот почему у меня всё "плыло".

Кстати Nola, вот здесь вы ошиблись:
Цитата Сообщение от Nola Посмотреть сообщение
Ширина картинки у вас 25 пикселей.
Каждый пиксель у вас кодируется 3 байтами.
25 * 3 = 75 байт
75 не делится нацело на 4.
И формат будет добавлять в конце строки несколько байт (в данном случае 3)
в конец строки добавится не 3 байта а 1, поскольку 76 делится нацело на 4 а 78 нет


Правда теперь интересует вопрос: как будет более правильно, читать файл сначала а выводить начиная со старших адресов в видеопамяти или наоборот, читать файл с конца а выводить с начала видеопамяти?
Миниатюры
Некорректный вывод BMP - VESA  
Изображения
 
0
1378 / 522 / 72
Регистрация: 21.07.2015
Сообщений: 1,308
10.01.2016, 22:44
Цитата Сообщение от Pycik Посмотреть сообщение
как будет более правильно, читать файл сначала а выводить начиная со старших адресов в видеопамяти или наоборот, читать файл с конца а выводить с начала видеопамяти?
У тебя памяти что ли не хватает? Читай в память целиком в ОЗУ и копируй в видеопамять.
Ну а так логичнее читать файл сначала и последовательно (рисовать соответственно снизу).
0
2 / 2 / 1
Регистрация: 24.03.2015
Сообщений: 13
10.01.2016, 23:09  [ТС]
Цитата Сообщение от shmkv Посмотреть сообщение
Ну а так логичнее читать файл сначала и последовательно (рисовать соответственно снизу).
Вот-вот, мне такой способ также показался более наглядным и логичным. Только в таком случае нужно будет потрудится чтобы правильно рассчитать начальный адрес для вывода в LFB, поскольку вывод у видеопамяти будет происходить начиная со старшего адреса.
0
Ушел с форума
Автор FAQ
 Аватар для Mikl___
16373 / 7685 / 1080
Регистрация: 11.11.2010
Сообщений: 13,759
11.01.2016, 03:20
Pycik,
вот здесь посмотри FAQ для раздела Assembler, MASM, TASM https://www.cyberforum.ru/cgi-bin/latex.cgi?\to "Вывод монохромного рисунка на экран в VESA-режиме 640x480x256"
1
1378 / 522 / 72
Регистрация: 21.07.2015
Сообщений: 1,308
11.01.2016, 03:44
Цитата Сообщение от Pycik Посмотреть сообщение
Только в таком случае нужно будет потрудится чтобы правильно рассчитать начальный адрес для вывода в LFB, поскольку вывод у видеопамяти будет происходить начиная со старшего адреса.
А в чем тут вообще может быть сложность? lfb_offset = x * bytes_per_pixel + y * bytes_per_line;

Добавлено через 6 минут
bytes_per_pixel = vesa_mode_bits_per_pixel / 8;
bytes_per_line = pith * bytes_per_pixel;
pith после установки видеорежима равен screen_width (если специально не менять).
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
11.01.2016, 03:44
Помогаю со студенческими работами здесь

Некорректный вывод числа на экран
В чем может быть проблемма, если после использывания процедуры OutInt proc aam add ax,3030h mov dl,ah ...

Некорректный вывод строки из резидента
Здравствуйте. Суть такова, нужно в резидентной программе при нажатии CTRL+S вывести сообщение, допустим "Hello". Возвращаем...

Некорректный вывод числа в консоль
Посчитал значение переменной ( проверил через дебаггер , считает правильно ), mov ax, @data mov ds,ax; mov...

Некорректный вывод значения числа в консоль
Написал прогу, но чёт не то выдаёт Есть массив, с клавы вводишь число, например, 110011. Первый и последний бит - номер строки. ;средние...

Некорректный вывод отрицательного результата вычисления (C+Assembler)
Доброй ночи. Само задание (-17*a+32-b)/(c-a*c/b) Работаем в dosbox(C+ASM). Проблема с этим минусом -17*a, выводит 65550. Не понимаю...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru