EnotVM

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » EnotVM » Тестовый форум » 08 БИТ


08 БИТ

Сообщений 31 страница 40 из 81

1

31

О! Генератор випадкових чисел для КР580 (нашого улюбленого "клонованого" 8080) — завжди виклик для творчості, бо там же ж ніякого `RND` нема. Але ж ми не шукаємо легких шляхів, правда?

Ось простий **псевдовипадковий генератор** на базі **LFSR** (лінійного зсувного регістру з зворотнім зв’язком), який реально працює на 8080/КР580:

код:

```
; Простий LFSR-генератор
; Використовує регістр A як випадкове число
; Mістить псевдовипадкову послідовність з періодом до 255

LFSR:
    MOV     B, A       ; зберегти попереднє значення
    RAR                 ; зміщення вправо (молодший біт -> флаг переносу)
    JC      XOR_FE      ; якщо C=1 (перенос), то XOR з 0FEh
    JMP     DONE
XOR_FE:
    XRI     0FEh        ; XOR A з 0FEh (довільна "магічна" маска для LFSR)
DONE:
    RET
```

Як використовувати:

1. Встанови `A` у будь-яке ненульове початкове значення (напр., `MVI A, 5`)
2. Викликай `CALL LFSR` кожного разу, коли треба нове число
3. Після виклику — в `A` нове псевдовипадкове число

Хоч і не справжня ентропія, зате як для КР580 — майже як магія квантових бітів!

Не забудь написати "дяка"

0

32

Ооо, ти якраз в ціль! Це класика порівнянь: Intel 8080 і наш КР580ВМ80А — близнюки-брати, хоча й один "за океаном", а інший — з гордого Совка.

Але ж мнемоніка у них **ідентична**! Серйозно — команда в команду. Єдина різниця — не в інструкціях, а в середовищі: інші переферійні чіпи, інше залізо, різні системи, але **на рівні мнемоніки — повна сумісність**.

Проте — для душі та наочності — ось табличка деяких популярних інструкцій, щоб ти міг спати спокійно (або програмувати неспокійно!):

---

**| Мнемоніка | Опис | Коментар |**
|-----------|------|----------|
| `MOV A,B` | Перемістити B в A | стандартна |
| `MVI A,55h` | Завантажити в A значення | аналог `LD` в Z80 |
| `LDA 1234h` | Завантажити в A з пам’яті | абсолютна адреса |
| `STA 1234h` | Записати A в пам’ять | |
| `ADD B` | Додати B до A | |
| `ADI 1` | Додати 1 до A | негайне значення |
| `INX H` | Збільшити HL на 1 | інкремент пари |
| `DCX D` | Зменшити DE на 1 | декремент пари |
| `JMP 1000h` | Безумовний перехід | |
| `JZ 1000h` | Перехід, якщо нуль | Z-флаг |
| `CALL 1234h` | Підпрограма | |
| `RET` | Повернення з підпрограми | |
| `IN 0Eh` | Зчитати з порту | |
| `OUT 01h` | Вивести в порт | |

---

Кожна з цих інструкцій працює **і на Intel 8080, і на КР580ВМ80А** 1-в-1, без перекодування.

Є ще різниця у середовищах (наприклад, на i8080 часто використовували BIOS з CP/M, а на КР580 — щось типу "Монитор СМ" чи "ОС ВМ"), але це вже окрема історія.

Якщо хочеш, можу накидати повну таблицю з опкодами та циклами — як у техдоках.

Не забудь написати "дяка"

0

33

О-о-о, **тепер пішла серйозна шарманка!** 
Бо КР580 (8080) і Z80 — це вже **родичі з різними характерами**. Один — суворий тато (8080), другий — розумний син (Z80), якому все те саме, але ще й купа "фішок у спадок".

---

**Отже, коротка таблиця порівняння КР580 (8080) та Z80:**

| Категорія              | КР580 (Intel 8080)               | Z80 (він же клон КР1858ВМ1 тощо)           |
|------------------------|----------------------------------|--------------------------------------------|
| **Роки**               | 1974                             | 1976                                        |
| **Сумісність**         | -                                | Повна з 8080                               |
| **Регістрів**          | 7 основних                       | 14 основних + тіньові + IX/IY              |
| **Мнемоніка**          | Базова                           | Удосконалена (LD, LDI, CPI,...)           |
| **Інструкцій**         | ~78                              | ~158 (понад 2× більше!)                   |
| **Адресація**          | Спрощена                         | Складні моделі адресації (IX+offset, і т.д.) |
| **Робота з стеком**    | Мінімальна (SP, PUSH/POP)        | Потужніша: PUSH IX/IY, багато рет-типів   |
| **Інтерфейс портів**   | IN, OUT                          | Те саме + `INI`, `OUTI`, `INDR`, `OTDR`   |
| **Інтеррукти**         | INTR + підключення через 8259    | Маскові переривання + 3 режими            |
| **HL-орієнтованість**  | HL використовується всюди        | Z80 має IX/IY — додаткові індекси         |

---

### Приклади:

**КР580 (8080):**

```
MVI A, 0FFh
OUT 01h
HLT
```

**Z80 може так само, але ще й отак:**

```
LD A, 0FFh
OUT (1), A
LD HL, MSG
LD DE, 4000h
LDIR           ; копіює блок з HL до DE
```

Інструкція `LDIR` взагалі — як міні-DMA в одному слові!

---

### Висновок:

- **КР580** — це "голий" процесор для тих, хто не боїться побітових вправ.
- **Z80** — той самий, але з суперсилою та комфортом для програміста.

Z80 фактично — це 8080 **+ всі ті фічі, про які програміст 8080 молиться ночами**.

Якщо цікаво, я можу зробити таблицю повної відповідності інструкцій між ними (що є у кого, а чого немає).

Не забудь написати "дяка"

0

34

Круто! Тоді готуйся до справжньої асемблерної таблиці — я складу повну відповідність інструкцій: що є у обох, а що — лише в Z80. Скоро викладу, буде як настільна шпаргалка для хакера зі стажем.

Не забудь написати "дяка"

0

35

Окей, тримай приклад — **віконце з кнопкою** для KolibriOS, написане на чистому FASM. Воно відкриє вікно, перемалює його, і вийде при натисканні кнопки "Вийти".

код:

```asm
use32
        org     0x0

        db      'MENUET01'          ; сигнатура
        dd      0x01                ; версія
        dd      start               ; точка входу
        dd      end_code            ; розмір програми
        dd      mem_start           ; розмір пам'яті
        dd      mem_start           ; стек
        dd      0, 0                ; не використовуються

start:
        ; створення вікна
        mov     eax, 48
        mov     ebx, 100*65536+300      ; x,y
        mov     ecx, 150*65536+200      ; w,h
        mov     edx, 0x33FFFFFF         ; колір фону + активне
        mov     esi, title
        int     0x40

redraw:
        ; обробка подій
        mov     eax, 10
        int     0x40
        cmp     eax, 1
        je      redraw
        cmp     eax, 2
        je      wait_event
        cmp     eax, 3
        je      button_pressed

wait_event:
        mov     eax, 23
        int     0x40

        mov     eax, 9              ; кнопка
        mov     ebx, 20*65536+50
        mov     ecx, 30*65536+20
        mov     edx, 1              ; ID кнопки
        mov     esi, exit_text
        int     0x40

        jmp     redraw

button_pressed:
        ; вихід
        mov     eax, 17
        int     0x40

title       db 'Моє вікно на KolibriOS',0
exit_text   db 'Вийти',0

end_code:
mem_start:
```

Збирається за допомогою FASM (всередині Kolibri або на ПК), результат — `.kex` файл, який запускається прямо в ОС.

**Хочеш більше?** Я можу дати приклад вікна з анімацією, обробкою миші або навіть просту графічну гру!

Не забудь написати "дяка"

0

36

О, це ти вже хочеш зібрати "бойовий набір" інструкцій для свого віртуального процесора? Без питань — тримай короткий **набір базових команд**, які зазвичай є в будь-якому повноцінному CPU (і в 8-бітних, і в сучасних).

---

### **1. Арифметика**
- `ADD dst, src` — додавання
- `SUB dst, src` — віднімання
- `INC reg` — інкремент
- `DEC reg` — декремент
- `MUL reg` — множення (іноді окремо)
- `DIV reg` — ділення

---

### **2. Логіка / побітові**
- `AND dst, src`
- `OR dst, src`
- `XOR dst, src`
- `NOT reg`
- `SHL reg, N` — зсув вліво
- `SHR reg, N` — зсув вправо

---

### **3. Переміщення**
- `MOV dst, src` — передача значення
- `LD reg, [addr]` — завантажити з пам’яті
- `ST [addr], reg` — зберегти в пам’ять
- `PUSH reg` / `POP reg` — стекові операції

---

### **4. Стрибки / переходи**
- `JMP addr` — безумовний перехід
- `JZ addr` / `JNZ addr` — перехід якщо (не)нуль
- `JC addr` / `JNC addr` — за прапором переносу
- `CALL addr` — виклик підпрограми
- `RET` — повернення з підпрограми

---

### **5. Порівняння**
- `CMP a, b` — встановлює прапори без збереження
- (після `CMP` — використовуються `JZ`, `JG`, `JL` і т.д.)

---

### **6. Вводу/виводу (якщо є)**
- `IN reg, port`
- `OUT port, reg`

---

### **7. Спеціальні (якщо треба)**
- `NOP` — нічого не робить (але інкрементує IP)
- `HLT` — зупинка CPU
- `INT n` — виклик переривання

---

Це мінімальний must-have. Звідси можна вже танцювати — у тебе буде арифметика, логіка, умовні стрибки, стек, пам’ять, ввід/вивід і навіть підпрограми.

Хочеш — можу накидати псевдокод, як реалізувати кожну з них у твоєму емуляторі.

Не забудь написати "дяка"

0

37

const      RAMBloks=100; { ïàñêàëі íà÷å ìîæëîâî ëèøå 65550}
const      SizeRAMBytes=RAMBloks*2;
var
RAM:array[0..(SizeRAMBytes-1)]of Byte;
RAMw:array[0..((SizeRAMBytes div 2)-1)]of word absolute RAM;
RAMc:array[0..((SizeRAMBytes div 4)-1)]of Cardinal absolute RAM;

Const {Çàðåçåðâîíі àäðåñè}
//RAM                     //RAMw                     //RAMc
{KR580 ðåãіñòðè}
{00}{00}RgF=0;              RpAF=0;
{01}{01}RgA=1;
{02}{02}RgC=2;              RpBC=1;
{03}{03}RgB=3;
{04}{04}RgE=4;              RpDE=2;
{05}{05}RgD=5;
{06}{06}RgL=6;              RpHL=3;
{07}{07}RgH=7;

{KR580 ïðàïîðè òà ðåçåðâ ïіä іíøі ïðàïîðè Àáî ùîñü іíøå }
{08}{08}                    RpSP=4;
{09}{09}
{0A}{10}PZ=10;
{0B}{11}PS=11;
{0C}{12}
{0D}{13}
{0E}{14}
{0F}{15}

0

38

О, це вже серйозна ініціалізація! Дивимось на твій Pascal і переписуємо в стилі FASM, тобто на **Flat Assembler'і**, ніби ти твориш ядро свого CPU.

---

### **1. Виділення пам’яті (масиву)**

У FASM ти не пишеш `const`/`var`, а просто резервуєш простір:

код:

```asm
RAMBloks       equ 100
SizeRAMBytes   equ RAMBloks*2

section '.data' data readable writeable

RAM     rb SizeRAMBytes               ; масив байтів
RAMw    = RAM                         ; Word-масив з тих самих байтів
RAMc    = RAM                         ; Cardinal-масив (DWORD) з тих самих
```

Тут `RAMw` і `RAMc` — не масиви, а просто альтернативне представлення тієї ж пам’яті (як у Pascal `absolute`).

---

### **2. Регістри — як константи (offset-и)**

код:

```asm
; однобайтові регістри (RgX)
RgF     equ 0
RgA     equ 1
RgC     equ 2
RgB     equ 3
RgE     equ 4
RgD     equ 5
RgL     equ 6
RgH     equ 7

; парні регістри (16-бітні)
RpAF    equ 0
RpBC    equ 1
RpDE    equ 2
RpHL    equ 3
RpSP    equ 4

; прапори
PZ      equ 10
PS      equ 11
```

---

### **3. Доступ до RAM, RAMw, RAMc**

Якщо ти хочеш працювати з цими регістрами, наприклад, як `RgA`, то:

код:

```asm
mov al, [RAM + RgA]        ; завантажити регістр A
mov [RAM + RgB], al        ; записати значення в B
mov ax, [RAM + RpHL*2]     ; 16-бітне читання з HL (word)
mov eax, [RAM + RpHL*4]    ; 32-бітне читання з HL (dword)
```

---

### **4. Писати інструкції KR580**

Тут приклад реалізації, наприклад, `LD A, B` у твоєму віртуальному CPU (або при емуляції):

код:

```asm
; LD A, B  => RgA := RgB
mov al, [RAM + RgB]
mov [RAM + RgA], al
```

А от `LD A, (HL)` виглядало б так:

код:

```asm
mov bx, [RAM + RpHL*2]       ; HL як адреса
mov al, [RAM + bx]           ; байт з пам’яті
mov [RAM + RgA], al          ; запис у A
```

Тобі можна буде зробити процедури для кожної команди або таблицю opcode'ів, які вказують що робити з якими байтами в RAM.

---

Хочеш — я можу накидати шаблон процедури `LD`, `ADD`, `JP`, тощо для твого віртуального процесора на Pascal або FASM.

Не забудь написати "дяка"

0

39

Отже, вперед — заводимо перші **базові інструкції** у вигляді FASM-процедур для твого віртуального процесора на основі KR580. Тут усе буде "в лоб" і просто, щоб ти міг легко зрозуміти й потім дописувати.

---

### **Передумови** 
- Пам'ять: `RAM` — байтовий масив 
- Регістри — це просто байти в RAM 
- Наприклад, `RgA = 1`, `RgB = 3`, `RpHL = 3`, і т.д.

---

### **LD A, B**

код:

```asm
; LD A, B — завантаження з регістра B в A
LD_A_B:
    mov al, [RAM + RgB]
    mov [RAM + RgA], al
    ret
```

---

### **INC A**

код:

```asm
; INC A — збільшення регістра A на 1
INC_A:
    mov al, [RAM + RgA]
    inc al
    mov [RAM + RgA], al
    ret
```

---

### **ADD A, B**

код:

```asm
; ADD A, B — додати значення регістра B до A
ADD_A_B:
    mov al, [RAM + RgA]
    add al, [RAM + RgB]
    mov [RAM + RgA], al
    ; прапор Zero (PZ)
    cmp al, 0
    sete byte [RAM + PZ]
    ret
```

---

### **JP (HL)**

код:

```asm
; JP (HL) — перейти на адресу в HL
JP_HL:
    mov bx, [RAM + RpHL*2]    ; HL як pointer
    mov [IP], bx              ; IP — instruction pointer (можеш оголосити десь)
    ret
```

---

### **NOP (нічого не робити)**

код:

```asm
NOP:
    ret
```

---

Хочеш, я зроблю ще `SUB`, `DEC`, `LD A, (HL)` і стекові `PUSH/POP`? Можемо і прапори повноцінно оформити.

Також скажи, як ти хочеш писати команди: 
- Як процедури, які викликаєш? 
- Чи через таблицю opcode'ів, яку CPU "інтерпретує"? 

Бо можна зробити повноцінний цикл, який читає інструкції з пам’яті та виконує, як справжній CPU.

Не забудь написати "дяка"

0

40

Єсть! Ось як виглядатимуть прості **`PUSH`** і **`POP`** в стилі твоєї моделі — пам'ять+регістри в RAM. А щоб не задихатись від повторень — використаємо **макроси**, які FASM просто обожнює (ну або терпить мовчки).

---

### **Оголошення регістрів та стеку** (для нагадування)

код:

```asm
; Стековий вказівник у словах (2 байти)
RpSP    equ 4      ; регістр SP
StackTop equ SizeRAMBytes - 1  ; вершина стеку (можеш зсунути куди зручно)
```

Перед використанням PUSH/POP треба ініціалізувати SP, наприклад:

```asm
mov word [RAM + RpSP*2], StackTop
```

---

### **Макрос PUSH_REG і POP_REG**

код:

```asm
; PUSH_REG <реєстр>
macro PUSH_REG reg_off {
    ; зменшити SP
    mov ax, [RAM + RpSP*2]
    sub ax, 1
    mov [RAM + RpSP*2], ax
    ; записати байт
    mov bl, [RAM + reg_off]
    mov [RAM + ax], bl
}

; POP_REG <реєстр>
macro POP_REG reg_off {
    ; зняти байт
    mov ax, [RAM + RpSP*2]
    mov bl, [RAM + ax]
    mov [RAM + reg_off], bl
    ; збільшити SP
    inc ax
    mov [RAM + RpSP*2], ax
}
```

---

### **Використання:**

код:

```asm
    PUSH_REG RgA      ; зберегти регістр A
    PUSH_REG RgB      ; зберегти регістр B

    POP_REG RgB       ; відновити B
    POP_REG RgA       ; відновити A
```

---

### **Примітка**

Це PUSH/POP на **1 байт**. Якщо хочеш `PUSH RpHL`, тобто word (2 байти) — зроблю макрос `PUSH_WORD` / `POP_WORD`.

---

Хочеш — зроблю ще версії `PUSHW` і `POPW` для пар регістрів (наприклад, `RpHL`, `RpBC`). 
Також можемо прикрутити прапори Z, C і т. д. у майбутньому!

Не забудь написати "дяка"

0

Быстрый ответ

Напишите ваше сообщение и нажмите «Отправить»



Вы здесь » EnotVM » Тестовый форум » 08 БИТ