Форум программистов, компьютерный форум, киберфорум
Assembler: DOS/Real Mode/16-bits
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.76/25: Рейтинг темы: голосов - 25, средняя оценка - 4.76
 Аватар для Agnarrock
0 / 0 / 0
Регистрация: 16.04.2017
Сообщений: 16
MASM

Вызов звука по нажатию клавиш Control+C (создание собственного прерывания)

17.11.2019, 18:24. Показов 5443. Ответов 4

Студворк — интернет-сервис помощи студентам
Задача состоит в генерации звука из динамика по нажатию комбинации клавиш Control+C (удержание первой и нажатие второй).
Код писал по различным пособиям и вроде бы по логике программа должна работать верно, но звуковой сигнал не издаётся и ещё после нажатия клавиши Esc (завершение программы) в строке оказывается какой-то мусор из символов.

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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
; Стек программы
ASTACK SEGMENT STACK
    ; Отвести под стек 1K байт = 8K бит
    ; 125 слов = 125 * 64 бит
    DW 125 DUP(?)
ASTACK ENDS
 
DATA SEGMENT
    KEEP_CS DW 0                ; Для хранения сегмента
    KEEP_IP DW 0                ; и смещения вектора прерывания
DATA ENDS
 
CODE SEGMENT
    ASSUME CS:CODE, DS:DATA, SS:ASTACK
    
ROUT PROC FAR
    PUSH AX                     ; Сохранение изменяемых регистров
 
    ; <!-- РАБОТА С ДИНАМИКОМ
 
    ;; 7 6 5 4 3 2 1 0   <- Битовый индекс
    ;; 1 0               канал 2: динамик ПК
    ;;     1 1           доступ: младший байт, затем старший байт
    ;;         0 1 1     прямоугольные волны (PWM (pulse-width modulation))
    ;;               0   просто двоичное число, а не BCD (binary-coded decimal)
    
    ;; 61h - адрес порта динамика
    ;; 42h - адрес порта таймера
 
    ;; Задание режима работы динамика 
    SUB   CX, CX                ; Обнуляем счётчик цикла 
    IN    AL, 61h               ; Получить текущее значение (регистр, ном_порта)
    AND   AL, 0FEh              ; Команда отключения
    OUT   61h, AL               ; Установка разряда 0 порта 61h в 0 для задания прямого управления динамиком 
    DIRECT: 
        OR    AL, 00000011b     ; Установить два младших бита
        OUT   61h, AL           ; Включить динамик 
        AND   AL, 0FDh          ; Очистить второй бит
        OUT   61h, AL           ; Выключить динамик 
    LOOP  DIRECT 
    
    ; Управление высотой звука динамика 
        MOV   AL, 10110110b     ; Канал 2, режим 2, оба байта
        OUT   43h, AL           ; Установка режима для 2-го канала 
        MOV   AX, 300           ; Выбор высоты звука 
        OUT   42h, AL           ; Включить таймер, который
                                ; будет выдавать импульсы на 
                                ; динамик с заданной частотой
        MOV   AL, AH 
        OUT   42h, AL           ; Занесение высоты звука в порт динамика 
        IN    AL, 61h           ; Получить состояние динамика
        MOV   AH, AL            ; И сохранить его в AH
        OR    AL, 00000011b     ; Установить два младших бита
        OUT   61h, AL           ; Включить динамик  
        SUB   CX, CX            ; Сбросить частоту импульсов динамика
    KILL_TIME:
        LOOP KILL_TIME          ; Цикл ожидания, во время которого работает динамик 
        MOV   AL, AH 
        OUT   61h, AL           ; Выключение динамика
    
    ; КОНЕЦ РАБОТЫ С ДИНАМИКОМ --!>
 
        POP  AX                 ; восстановление регистров
        MOV  AL, 20h
        OUT  20h, AL            ; Очищaeм IMR (Interrupt Mask Register) в кoнцe пpoгpaммы
        IRET
ROUT  ENDP
 
MAIN PROC FAR
        PUSH DS
        XOR AX, AX
        PUSH AX
        MOV AX, DATA
        MOV DS, AX
 
        MOV  AH, 35h            ; Получаем адрес обработчика прерывания
        MOV  AL, 05h            ; Записываем номер прирывания
 
        ;; После вызова прерывания INT 21h в регистре ES
        ;; возвращается значение сегмента обработчика указанного прерывания.
        ;; В регистре BX взвращается значение смещения
        ;; обработчика указанного прерывания.
 
        INT  21H
        MOV  KEEP_IP, BX        ; Запоминание смещения
        MOV  KEEP_CS, ES        ; и сегмента вектора прерывания
    
        PUSH DS
        MOV  DX, OFFSET ROUT    ; смещение для процедуры в DX
        MOV  AX, SEG ROUT       ; сегмент процедуры
        MOV  DS, AX             ; помещаем в DS
        MOV  AH, 25h            ; функция установки вектора
        MOV  AL, 05h            ; номер вектора
        INT  21H                ; меняем прерывание
        POP DS
        jmp begin
    bell:
        int 05h
    begin:
        in AL, 60h              ; ожидаем нажатие
        cmp AL, 01h             ; клавиши Esc
        je exit
        cmp AL, 2Eh             ; клавиши C
        jne begin
        mov AH, 02h             ; проверяем
        int 16h                 ; на
        cmp AL, 3h              ; зажатый Control
        je BELL
        jmp BEGIN
    exit:
        CLI
        ;; Восстановление старого прерывания
        PUSH DS
        MOV  DX, KEEP_IP
        MOV  AX, KEEP_CS
        MOV  DS, AX
        MOV  AH, 25h
        MOV  AL, 05h
        INT  21H                ; Восстанавливаем старый вектор прерывания
        POP  DS
        STI
        RET
    MAIN ENDP
 
CODE ENDS
 
END MAIN
В чём может быть проблема? Быть может у меня где-то неправильно выставлена задержка сигнала или что-то в этом роде?
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
17.11.2019, 18:24
Ответы с готовыми решениями:

Вызов сочетаний клавиш по нажатию на button
Доброе времени суток, подскажите пожалуйста, как вызвать сочетание клавиш такие как: &quot;CTRL + Z&quot;,&quot;CTRL + X&quot;,&quot;CTRL +...

Вызов события по нажатию комбинации клавиш в событии OnKeyPress оператором case
Здравствуйте! Для обработки события нажатия на клавишу клавиатуры существует событие OnKeyPress. Например, в блокноте, вызов действия путём...

Написание собственного прерывания
Доброго времени суток. Нужно написать собственное прерывание, которое выводит на экран строку. Написать, вроде, написал, но при прогоне в...

4
Прощай, Мир!
 Аватар для proc3nt
1673 / 831 / 253
Регистрация: 26.05.2012
Сообщений: 3,056
17.11.2019, 19:40
Цитата Сообщение от Agnarrock Посмотреть сообщение
; Отвести под стек 1K байт = 8K бит
; 125 слов = 125 * 64 бит
Цитата Сообщение от Agnarrock Посмотреть сообщение
DW 125 DUP(?)
125 слов = 125 * 16 бит = 125 * 2 байта = 250 байт..
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8655 / 4490 / 1669
Регистрация: 01.02.2015
Сообщений: 13,898
Записей в блоге: 12
17.11.2019, 21:14
Лучший ответ Сообщение было отмечено Agnarrock как решение

Решение

Agnarrock, длительность звука вы задаёте циклом в строках 55-57.
Это неправильный подход.
Этот код вы взяли из какой-то древней книги, когда скорость процессора не превышала 8-16МГц. На современных - цикл задержки выполнится за несколько микросекунд.

Лучше перехватить и прерывание таймера int 1Ch.
В обработчике прерывания держать две переменные - SoundOn и CountDown.
В обработчике будут выполнятся следующие действия (покажу в псевдокоде):
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  if(SoundOn > 0)  //условие включения динамика
  {
    SoundOn=0;
    CountDown=18;  //время 1 секунда
    код включения звука
  }
  else
  {  //динамик или включён или отключён
    if(CountDown > 0)  //если включён - продолжить отсчёт
    {
      CountDown--;
      if(CountDown==0)
      {
        код отключения звука
      }
    }
  }
При этом, переменную SoundOn включает обработчик прерывания по Ctrl-C.

Попробуйте так.
Код включения и отключения звука можете сверить с аналогичным в соседней теме
Воспроизведение нот
Включение:
Assembler
1
2
3
4
5
6
7
8
9
    mov al, 10110110b   ; канал 2, режим 3
    out 43h, al
    mov al, 9ah          ; младший байт делителя частоты 4a9h
    out 42h, al
    mov al, 4h      ; старший байт делителя частоты
    out 42h, al
    in  al, 61h     ; текущее состояние порта 61h в AL
    or  al, 00000011b   ; установить биты 0 и 1 в 1 (разрешить работу динамика и включить его)
    out 61h, al     ; теперь динамик включен
Отключение:
Assembler
1
2
3
    in  al, 61h
    and al, 11111100b   ; обнулить младшие два бита
    out 61h, al     ; теперь динамик выключен
Добавлено через 50 минут
Смотрите, вот пример реализации на ассемблере псевдокода.
Здесь в основной программе при нажатии любой клавиши кроме ESC устанавливается флаг SoundOn. При вызове прерывания таймера этот флаг обрабатывается - он сбрасывается и включается динамик на несколько отсчётов таймера (в данном случае на 9, что равно 1/2 секунды). При следующих вызовах отсчёт уменьшается и при нуле - отключается динамик.

Так и вы - в вашем обработчике прерывания Ctrl-C выставляете флаг SoundOn, а дальше всё само обрабатывается.
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
.model medium
 
.stack 200h
 
.data
        CrLf            db      0Dh, 0Ah, '$'
        msgPressAnyKey  db      0Dh, 0Ah, 'Press any key to exit...', '$'
        SoundOn         dw      0
        CountDown       dw      0
 
        kbESC           equ     1Bh
.code
 
; Обработчик прерывания 1Ch (пользовательский обработчик IRQ0)
int1Ch_handler  proc    far
        PUBLIC  old_int1Ch
 
        push    ax
        push    ds
        mov     ax,     @data
        mov     ds,     ax
        cmp     [SoundOn],      0                       ;  if(SoundOn > 0)  //условие включения динамика
        je      Else1Ch                                 ;  {
                mov     [SoundOn],      0               ;    SoundOn=0;
                mov     [CountDown],    9               ;    CountDown=18;  //время 1 секунда
                                                        ;    код включения звука
                mov al, 10110110b                       ; канал 2, режим 3
                out 43h, al
                mov al, 9ah                             ; младший байт делителя частоты 4a9h
                out 42h, al
                mov al, 4h                              ; старший байт делителя частоты
                out 42h, al
                in  al, 61h                             ; текущее состояние порта 61h в AL
                or  al, 00000011b                       ; установить биты 0 и 1 в 1 (разрешить работу динамика и включить его)
                out 61h, al                             ; теперь динамик включен
                jmp     Exit1Ch                         ;  }
        Else1Ch:                                        ;  else
                                                        ;  {  //динамик или включён или отключён
                cmp     [CountDown],    0               ;    if(CountDown > 0)  //если включён - продолжить отсчёт
                je      Exit1Ch                         ;    {
                        dec     [CountDown]             ;      CountDown--;
                        jnz     Exit1Ch                 ;      if(CountDown==0)
                                                        ;      {
                                                        ;        код отключения звука
                                in  al, 61h
                                and al, 11111100b       ; обнулить младшие два бита
                                out 61h, al             ; теперь динамик выключен
                                                        ;      }
                                                        ;    }
                                                        ;  }
Exit1Ch:
        pop     ds
        pop     ax
 
        db      0EAh                    ; команда jmp far
old_int1Ch      dd      0               ; адрес старого обработчика
int1Ch_handler  endp
 
main    proc
        ;инициализация сегментного регистра ds адресом сегмента данных
        mov     ax,     @data
        mov     ds,     ax
 
        ;установка обработчика прерывания
        mov     ax,     351Ch           ; AH = 35h, AL = номер прерывания
        int     21h                     ; получить адрес обработчика
        mov     word ptr old_int1Ch, bx ; и записать его в old_int1Ch
        mov     word ptr old_int1Ch+2, es
        push    ds
        mov     ax,     251Ch           ; AH = 25h, AL = номер прерывания
        mov     dx, offset int1Ch_handler  ; DS:DX - адрес обработчика
        mov     bx, seg int1Ch_handler
        mov     ds,     bx
        int     21h                     ; установить обработчик
        pop     ds
 
        @@repeat:
                mov     ah,     00h
                int     16h
                cmp     al,     kbESC
                je      @@break
                mov     [SoundOn],      1
        jmp     @@repeat
@@break:
 
        ;восстановление вектора прерывания
        push    ds
        mov     ax,     251Ch           ; АН = 25h, AL = номер прерывания
        lds     dx,     dword ptr old_int1Ch   ; DS:DX = адрес обработчика
        int     21h                     ; восстановить старый обработчик
        pop     ds
        ;ожидание нажатия любой клавиши
        mov     ah,     09h
        lea     dx,     [msgPressAnyKey]
        int     21h
 
        mov     ah,     00h
        int     16h
 
        ;завершение программы
        mov     ax,     4C00h
        int     21h
main    endp
 
end     main
1
 Аватар для Agnarrock
0 / 0 / 0
Регистрация: 16.04.2017
Сообщений: 16
17.11.2019, 21:54  [ТС]
В результате для себя решил данную проблему таким способом:

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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
; Стек программы
ASTACK SEGMENT STACK
    ; Отвести под стек 1K байт = 8K бит
    ; 512 слов = 512 * 16 бит = 512 * 2 байта = 1024 байт
    DW 512 DUP(?)
ASTACK ENDS
 
DATA SEGMENT
    KEEP_CS DW 0                ; Для хранения сегмента
    KEEP_IP DW 0                ; и смещения вектора прерывания
    TONE DW 4351                ; Частота звука
    TIME DW 1000                ; Длительность звукового сигнала
DATA ENDS
 
CODE SEGMENT
    ASSUME CS:CODE, DS:DATA, SS:ASTACK
    
SOUND PROC FAR
    ;; Сохранение изменяемых регистров
    PUSH AX
    PUSH CX
    PUSH DX
    PUSH BX
 
    ; <!-- РАБОТА С ДИНАМИКОМ
 
        ;; 7 6 5 4 3 2 1 0   <- Битовый индекс
        ;; 1 0               канал 2: динамик ПК
        ;;     1 1           доступ: младший байт, затем старший байт
        ;;         0 1 1     прямоугольные волны (PWM (pulse-width modulation))
        ;;               0   просто двоичное число, а не BCD (binary-coded decimal)
        
        ;; 61h - адрес порта динамика
        ;; 42h - адрес порта таймера
        
        ; Управление высотой звука динамика 
            MOV   AL, 10110110b     ; Канал 2, режим 2, оба байта
            OUT   43h, AL           ; Установка режима для 2-го канала (командный регистр (порт 43h))
            MOV   AX, TONE          ; Установка высоты звука.
            MOV   BX, TIME          ; Установка длительности звука
            OUT   42h, AL           ; Включить таймер, который
                                    ; будет выдавать импульсы на 
                                    ; динамик с заданной частотой
                                    ; (в порт 42h младшее слово ax:al)
            MOV   AL, AH
            OUT   42h, AL           ; Занесение высоты звука в порт динамика
                                    ; (в порт 42h старшее слово ax:ah)
 
            ;; Задание режима работы динамика
            IN    AL, 61h           ; Получить состояние динамика
            MOV   AH, AL            ; И сохранить его в AH
            OR    AL, 00000011b     ; Установить два младших бита (инициализация динамика)
            OUT   61h, AL           ; Включить динамик  (подаём ток в поркт 61h)
            
            ; Цикл ожидания, во время которого работает динамик.
            _KILL_TIME_1: MOV CX, 2083
                _KILL_TIME_2: LOOP _KILL_TIME_2
            DEC BX                  ; Декремент для BX
            JNZ _KILL_TIME_1        ; Перейти, если не равно ZF = 0
 
            MOV   AL, AH 
            OUT   61h, AL           ; Выключение динамика
        
        ; КОНЕЦ РАБОТЫ С ДИНАМИКОМ --!>
 
            ;; Восстановление регистров
            POP BX
            POP DX
            POP CX
            POP AX
 
        RET
 
SOUND  ENDP
 
SUBR_INT PROC FAR 
    PUSH DX                     ; Cохранение изменяемых регистров
    PUSH AX                
    
    CALL SOUND
    
    MOV AL, 20H                 ; Разрешение обработки прерываний с более низкими уровнями,
    OUT 20H, AL                 ; чем только что обработанное
    
    POP AX                      ; Восстановление регистров
    POP DX 
    IRET
SUBR_INT ENDP
 
MAIN PROC FAR
        PUSH DS
        XOR AX, AX
        PUSH AX
        MOV AX, DATA
        MOV DS, AX
 
        MOV  AH, 35h            ; Получаем адрес обработчика прерывания (функция получения вектора)
        MOV  AL, 23h            ; Записываем номер прерывания (вектора)
 
        ;; После вызова прерывания INT 21h в регистре ES
        ;; возвращается значение сегмента обработчика указанного прерывания.
        ;; В регистре BX взвращается значение смещения
        ;; обработчика указанного прерывания.
 
        INT  21H
        MOV  KEEP_IP, BX        ; Запоминание смещения
        MOV  KEEP_CS, ES        ; и сегмента вектора прерывания
    
        PUSH DS
        MOV  DX, OFFSET SUBR_INT    ; смещение для процедуры в DX
        MOV  AX, SEG SUBR_INT       ; сегмент процедуры
        MOV  DS, AX                 ; помещаем в DS
            MOV  AH, 25h            ; функция установки вектора
            MOV  AL, 23h            ; номер вектора
            INT  21H                ; меняем прерывание
        POP DS
 
    BEGIN:
        XOR AH, AH              ; Функция 00h
        INT 16h                 ; Читать (ожидать) следующую нажатую клавишу
        in AL, 60h              ; ожидаем нажатие
        cmp AL, 01h             ; клавиши Esc
        je EXIT                 ; Если она - завершаем программу
        cmp AL, 2Eh             ; Сравнение клавиши с 'C'
        jne BEGIN               ; Перейти, если не равно
        mov AH, 02h             ; проверяем
        int 16h                 ; на
        cmp AL, 3h              ; зажатый Control
        INT 23H
        jmp BEGIN
    EXIT:
        CLI                     ; Сброс флага прерывания 
        ;; Восстановление старого прерывания
        PUSH DS
        MOV  DX, KEEP_IP        ; Смещение для процедуры 
        MOV  AX, KEEP_CS        ; Сегмент процедуры 
        MOV  DS, AX             ; Помещаем в DS
        MOV  AH, 25h            ; Функция установки вектора 
        MOV  AL, 05h
        INT  21H                ; Восстанавливаем старый вектор прерывания
        POP  DS
        STI                     ; Установка флага прерывания
        RET
    MAIN ENDP
 
CODE ENDS
 
END MAIN
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8655 / 4490 / 1669
Регистрация: 01.02.2015
Сообщений: 13,898
Записей в блоге: 12
17.11.2019, 22:21
Формально это не правильное решение - ведь в обработчиках прерываний не должно быть ожиданий, пауз.
Логика должна строиться по принципу - выставил разрешение другому процессу, а тот пусть сам разбирается.

Подозреваю, что ассемблер для устаревшей DOS изучаете для более лёгкого перехода к обучению программирования микроконтроллеров. Там ведь многое построено на таком же принципе.

Добавлено через 1 минуту
Правильное решение - в обработчике прерывания Ctrl-C вместо вызова call Sound, нужно было mov [SoundOn], 1, а остальное делает обработчик таймера.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
17.11.2019, 22:21
Помогаю со студенческими работами здесь

Написание собственного прерывания (проверьте)
Здравствуйте! Задание состоит в том, что надо написать новый обработчик прерывания, заменить им существующий, после чего восстановить...

Вызов прерывания в обработке прерывания
В программе,нажатие кнопки вызывает прерывание,в котором оно обрабатывается.Попутно в обработке этого прерывания запускается таймер по...

Обработка прерывания, генерируемого при нажатии клавиши Control+C
Задание:Нужно написать своё прерывание,генерируемое при нажатии клавиши Control+C. Программа должна выдавать звуковой сигнала(печать...

По нажатию кнопки прекратить выполнение прерывания 1Ch
Здравствуйте. Нужна помощь с выполнением задания. Задание заключается в том, чтобы переопределить прерывание 1Ch на вывод сообщения на...

Вызов внутреннего прерывания из внешнего
Всем День добрый, может кто подсказать правильно ли организован вызов прерывания по совпадению ? просто это моя первая программа для МК. И...


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

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru