EnotVM

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

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


Вы здесь » EnotVM » Тестовый форум » 32 Бита


32 Бита

Сообщений 11 страница 20 из 33

1

11

Ось глянь, що вийшло
Думаю розберешся
в квадратних дужках (закоментовано) процедури, - {MOV(Rg1,Value)} які генерують
а поруч результат, - A:=4294967295; того, що саме вона генерує.
Тут майже всі команди, які будуть емітуватись, окрім доступу до пам'яті.
З пам'яттю ніякі дії проводитись не будуть лише присвоювання до регістрів та
завантаження числового значення,тобто? - Mov, Mvi.
Думаю, що немає потреби проводити якісь дії (операції) з пам'яттю. Усі дії (операції),
потім зчитуються та записуються в пам'ять.
Усі команди в програмі, як набір команд, для тестування.
Це не є якась програма, яка щось виконує.
Оціни.
Далі...
Питання:
Якщо я зміню всі "Cardinal" на "Longint" (для сумісності з турбопаскалем),
то все буде працювати, як треба ?
Звісно. до потрібно в Дельфі зроблю Cardinal(), а в паскалі type TCardinal=record Hi:Word;Lo:Word; end;
та напишу процедури відповідні обробці типа TCardinal

Код:
Program Enot;
{$APPTYPE CONSOLE}
type {Byte 0..255} {Word 0..65535}       DWord=Cardinal;{0..4294967295}{Longword}
const  SizeRAMBytes=65535;
var RAMdw:array[0..((SizeRAMBytes div 2)+1)]of DWord;
var RAMw:array[0..((SizeRAMBytes div 2)+1)]of Word;
var RAM:array[0..SizeRAMBytes]of Byte absolute RAMw;

Procedure StartProgram;
Var A,B,C,D, ESP:Dword;
label m1;
         Procedure Test1;begin end;
BEGIN
  ESP:=(SizeRAMBytes div 4);
m1:
{MOV(Rg1,Value)}       A:=4294967295;
{MOV(Rg1,Value)}       B:=4294967295;
{MOV(Rg1,Value)}       C:=4294967295;
{MOV(Rg1,Value)}       D:=4294967295;
{MOV(Rg1,Rg2)}         A:=A;
{MOV(Rg1,Rg2)}         A:=B;
{MOV(Rg1,Rg2)}         A:=C;
{MOV(Rg1,Rg2)}         A:=D;
{MOV(Rg1,Rg2)}         B:=A;
{MOV(Rg1,Rg2)}         B:=B;
{MOV(Rg1,Rg2)}         B:=C;
{MOV(Rg1,Rg2)}         B:=D;
{MOV(Rg1,Rg2)}         C:=A;
{MOV(Rg1,Rg2)}         C:=B;
{MOV(Rg1,Rg2)}         C:=C;
{MOV(Rg1,Rg2)}         C:=D;
{MOV(Rg1,Rg2)}         D:=A;
{MOV(Rg1,Rg2)}         D:=B;
{MOV(Rg1,Rg2)}         D:=C;
{MOV(Rg1,Rg2)}         D:=D;
{INC_(Rg1)}            INC(A);
{INC_(Rg1)}            INC(B);
{INC_(Rg1)}            INC(C);
{INC_(Rg1)}            INC(D);
{DEC_(Rg1)}            DEC(A);
{DEC_(Rg1)}            DEC(B);
{DEC_(Rg1)}            DEC(C);
{DEC_(Rg1)}            DEC(D);
{ADD(Rg1,Rg2,Value)}   A:=(D+56);
{ADD(Rg1,Rg2,Rg3)}     A:=(D+C);
{SUB(Rg1,Rg2,Value)}   A:=(D-56);
{SUB(Rg1,Rg2,Rg3)}     A:=(D-C);
{AND(Rg1,Rg2,Value)}   A:=(D AND 56);
{AND(Rg1,Rg2,Rg3)}     A:=(D AND C);
{XOR(Rg1,Rg2,Value)}   A:=(D XOR 56);
{XOR(Rg1,Rg2,Rg3)}     A:=(D XOR C);
{ OR(Rg1,Rg2,Value)}   A:=(D  OR 56);
{ OR(Rg1,Rg2,Rg3)}     A:=(D  OR C);
{NOT(Rg1,Rg2)}         C:=(NOT D);
{ SHL(Rg1,Rg2,Value)}  A:=(D  SHL 56);
{ SHL(Rg1,Rg2,Rg3)}    A:=(D  SHL C);
{ SHR(Rg1,Rg2,Value)}  A:=(D  SHR 56);
{ SHR(Rg1,Rg2,Rg3)}    A:=(D  SHR C);
{ PUSH(Value)}         DEC(ESP);RAMdw[ESP]:=100;
{ PUSH(Rg1)}           DEC(ESP);RAMdw[ESP]:=B;
{ POP(Value)}          D:=RAMdw[ESP];INC(ESP);
{ JE GotoIs(Rg1,Value)}    IF A=10 then goto m1;
{ JE GotoIs(Rg1,Rg2)}    IF A=B then goto m1;
{ JNE GotoNotIs(Rg1,Value)}    IF A<>10 then goto m1;
{ JNE GotoNotIs(Rg1,Rg2)}    IF A<>B then goto m1;
{ JB GotoLess(Rg1,Value)}    IF Cardinal(A)<Cardinal(10) then goto m1;
{ JB GotoLess(Rg1,Rg2)}    IF Cardinal(A)<Cardinal(B) then goto m1;
{ JA GotoMore(Rg1,Value)}    IF Cardinal(A)>Cardinal(10) then goto m1;
{ JA GotoMore(Rg1,Rg2)}    IF Cardinal(A)>Cardinal(B) then goto m1;
{ JB GotoLess(Rg1,Value)}    IF Cardinal(A)<Cardinal(10) then goto m1;
{ JB GotoLess(Rg1,Rg2)}    IF Cardinal(A)<Cardinal(B) then goto m1;
{ JA GotoMore(Rg1,Value)}    IF Cardinal(A)>Cardinal(10) then goto m1;
{ JA GotoMore(Rg1,Rg2)}    IF Cardinal(A)>Cardinal(B) then goto m1;
{ JBE GotoLess(Rg1,Value)}    IF Cardinal(A)<=Cardinal(10) then goto m1;
{ JBE GotoLess(Rg1,Rg2)}    IF Cardinal(A)<=Cardinal(B) then goto m1;
{ JAE GotoLess(Rg1,Value)}    IF Cardinal(A)>=Cardinal(10) then goto m1;
{ JaE GotoLess(Rg1,Rg2)}    IF Cardinal(A)>=Cardinal(B) then goto m1;
{ JL GotoLessz(Rg1,Value)}    IF Longint(A)<Longint(10) then goto m1;
{ JL GotoLessz(Rg1,Rg2)}    IF Longint(A)<Longint(B) then goto m1;
{ JG GotoMorez(Rg1,Value)}    IF Longint(A)>Longint(10) then goto m1;
{ JG GotoMorez(Rg1,Rg2)}    IF Longint(A)>Longint(B) then goto m1;
{ JL GotoLessz(Rg1,Value)}    IF Longint(A)<Longint(10) then goto m1;
{ JL GotoLessz(Rg1,Rg2)}    IF Longint(A)<Longint(B) then goto m1;
{ JG GotoMorez(Rg1,Value)}    IF Longint(A)>Longint(10) then goto m1;
{ JG GotoMorez(Rg1,Rg2)}    IF Longint(A)>Longint(B) then goto m1;
{ JLE GotoLessz(Rg1,Value)}    IF Longint(A)<=Longint(10) then goto m1;
{ JLE GotoLessz(Rg1,Rg2)}    IF Longint(A)<=Longint(B) then goto m1;
{ JAE GotoLess(Rg1,Value)}    IF Cardinal(A)>=Cardinal(10) then goto m1;
{ JGE GotoLessz(Rg1,Rg2)}    IF Longint(A)>=Longint(B) then goto m1;
{ JE CallIs(Rg1,Value)}    IF A=10 then Test1;
{ JE CallIs(Rg1,Rg2)}    IF A=B then Test1;
{ JNE CallNotIs(Rg1,Value)}    IF A<>10 then Test1;
{ JNE CallNotIs(Rg1,Rg2)}    IF A<>B then Test1;
{ JB CallLess(Rg1,Value)}    IF Cardinal(A)<Cardinal(10) then Test1;
{ JB CallLess(Rg1,Rg2)}    IF Cardinal(A)<Cardinal(B) then Test1;
{ JA CallMore(Rg1,Value)}    IF Cardinal(A)>Cardinal(10) then Test1;
{ JA CallMore(Rg1,Rg2)}    IF Cardinal(A)>Cardinal(B) then Test1;
{ JB CallLess(Rg1,Value)}    IF Cardinal(A)<Cardinal(10) then Test1;
{ JB CallLess(Rg1,Rg2)}    IF Cardinal(A)<Cardinal(B) then Test1;
{ JA CallMore(Rg1,Value)}    IF Cardinal(A)>Cardinal(10) then Test1;
{ JA CallMore(Rg1,Rg2)}    IF Cardinal(A)>Cardinal(B) then Test1;
{ JBE CallLess(Rg1,Value)}    IF Cardinal(A)<=Cardinal(10) then Test1;
{ JBE CallLess(Rg1,Rg2)}    IF Cardinal(A)<=Cardinal(B) then Test1;
{ JAE CallLess(Rg1,Value)}    IF Cardinal(A)>=Cardinal(10) then Test1;
{ JaE CallLess(Rg1,Rg2)}    IF Cardinal(A)>=Cardinal(B) then Test1;
{ JL CallLessz(Rg1,Value)}    IF Longint(A)<Longint(10) then Test1;
{ JL CallLessz(Rg1,Rg2)}    IF Longint(A)<Longint(B) then Test1;
{ JG CallMorez(Rg1,Value)}    IF Longint(A)>Longint(10) then Test1;
{ JG CallMorez(Rg1,Rg2)}    IF Longint(A)>Longint(B) then Test1;
{ JL CallLessz(Rg1,Value)}    IF Longint(A)<Longint(10) then Test1;
{ JL CallLessz(Rg1,Rg2)}    IF Longint(A)<Longint(B) then Test1;
{ JG CallMorez(Rg1,Value)}    IF Longint(A)>Longint(10) then Test1;
{ JG CallMorez(Rg1,Rg2)}    IF Longint(A)>Longint(B) then Test1;
{ JLE CallLessz(Rg1,Value)}    IF Longint(A)<=Longint(10) then Test1;
{ JLE CallLessz(Rg1,Rg2)}    IF Longint(A)<=Longint(B) then Test1;
{ JAE CallLess(Rg1,Value)}    IF Cardinal(A)>=Cardinal(10) then Test1;
{ JGE CallLessz(Rg1,Rg2)}    IF Longint(A)>=Longint(B) then Test1;

Writeln('A=',A,'   B=',B,'   C=',C,'   D=',D);Readln;
END;
BEGIN StartProgram; END.

0

12

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

Щодо питання про `Cardinal` → `Longint`:
**Так, все буде працювати**, але з кількома важливими зауваженнями:

---

### 1. **Діапазон значень:**

* `Cardinal` = `0..4294967295`
* `Longint` = `-2147483648..2147483647`
  Отже, будь-яке присвоєння значення понад `2147483647` призведе до переповнення і спотворення результату.

Наприклад:

```pascal
A := 4294967295; // як Cardinal = $FFFFFFFF
```

Якщо `A` — `Longint`, отримаєш `-1`, що може бути навіть зручно в деяких умовах (як у x86, де -1 — це \$FFFFFFFF), але небезпечно, якщо не контролювати це явно.

---

### 2. **Заміна типів:**

Якщо зробиш тип:

```pascal
type TCardinal = record
  Lo, Hi: Word;
end;
```

...і напишеш допоміжні процедури для конвертації до/з `Longint` або `Cardinal`, — чудова ідея. Але тоді доведеться реалізувати ручні арифметичні та логічні операції для `TCardinal`.

---

### 3. **Порівняння:**

Як ти вже зробив у коді — класно:

* `Cardinal(A) > Cardinal(B)` — для **unsigned**
* `Longint(A) > Longint(B)` — для **signed**

Якщо `A`, `B` стануть `Longint`, для unsigned порівняння доведеться кожен раз писати `Cardinal(A)` в Delphi, а в Turbo Pascal — щось типу `ToCardinal(A)`.

---

### 4. **Можливий варіант спільного типу:**

Для сумісності обох середовищ можеш зробити щось таке:

```pascal
{$ifdef FPC}
type TCardinal = Longint;
function Cardinal(x: TCardinal): Longint; inline;
begin
  Cardinal := Longint(x) and $FFFFFFFF;
end;
{$else}
type TCardinal = Cardinal;
{$endif}
```

І будеш у Turbo Pascal працювати з 32-бітами через Longint, а в Delphi — напряму.

---

Загалом, **дуже правильно зроблено**! І стиль у тебе добре структурований — видно, що думаєш на рівні архітектури. Залишається тільки розписати окремо модуль для операцій з `TCardinal`, і тоді можна сміливо портувати все на FASM, C або Rust.

Хочеш — можу допомогти з такими процедурами для `TCardinal`?

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

0

13

Звісно, ось деякі ресурси, які можуть бути корисними для розробки під DOS за допомогою Free Pascal:

Free Pascal Compiler для DOS (GO32v2):
Free Pascal підтримує розробку під DOS за допомогою GO32v2-розширення. Ви можете завантажити відповідні версії з офіційного сайту:

Free Pascal 3.2.2 для DOS (GO32v2)

Free Pascal 3.2.0 для DOS (GO32v2)

Free Pascal 2.6.4 для DOS (GO32v2)
SourceForge
+3
SourceForge
+3
SourceForge
+3

Free Pascal для MSDOS (i8086):
Існує також версія Free Pascal, яка підтримує компіляцію для 16-бітного MSDOS:

Free Pascal 3.2.2 для MSDOS (i8086)
SourceForge

PascalGUI для Android:
Якщо вас цікавить мобільна розробка на Pascal, ви можете ознайомитися з PascalGUI для Android. Це середовище дозволяє писати та запускати Pascal-програми на Android-пристроях. Детальніше:

PascalGUI 4.05 для Android
Трешбокс.ру

Якщо вам потрібна допомога з налаштуванням середовища або виникнуть питання щодо компіляції під DOS, не соромтеся звертатися!

Джерела

Я обираю цю відповідь
ChatGPT
Відповідь 2
Так, Free Pascal (FPC) дійсно дозволяє створювати 32-бітні програми для DOS за допомогою розширювача GO32v2, який базується на DJGPP. Це означає, що ти можеш використовувати 32-бітні регістри, такі як EAX, EBX тощо, а також типи DWord, Cardinal, LongInt і працювати з 32-бітною арифметикою.
SourceForge

🔧 Де завантажити FPC для DOS (GO32v2)
Офіційна сторінка завантаження FPC для DOS:

FPC 3.2.2 для DOS (GO32v2)
Завантажити можна тут:
freepascal.org

Там доступні два варіанти:

dos322full.zip (75 МБ) — повний пакет з документацією та вихідними кодами.

dos322.zip (33 МБ) — без документації та вихідних кодів.

Зверни увагу, що ці пакети призначені для запуску в середовищі DOS або DOS-емуляторах, таких як DOSBox.

📱 Щодо мобільного PascalGUI
PascalGUI — це мобільний компілятор для Android, який дозволяє писати та компілювати Pascal-програми безпосередньо на смартфоні. Він використовує Free Pascal Compiler (FPC) у якості компілятора. Однак, версія FPC, яка використовується в PascalGUI, може відрізнятися від офіційних релізів, і точну версію слід уточнювати в налаштуваннях додатку або у розробника.

🛠️ Як компілювати для DOS
Після встановлення FPC з підтримкою GO32v2, ти можеш компілювати програми для DOS за допомогою наступної команди:

bash
Копіювати код
fpc -Tgo32v2 program.pas
Це створить 32-бітний DOS-екзешник, який можна запускати в реальному DOS або в емуляторі, такому як DOSBox.

🧠 Поради
DJGPP: GO32v2 базується на DJGPP, тому переконайся, що всі необхідні компоненти встановлені.

DOSBox: Для тестування та запуску програм у сучасних системах рекомендується використовувати DOSBox.

Turbo Pascal: Якщо ти звик до Turbo Pascal, FPC з GO32v2 дозволить тобі використовувати знайомий синтаксис з розширеними можливостями.
SourceForge

Якщо потрібна допомога з налаштуванням середовища або виникнуть додаткові запитання, звертайся!

Джерела

Я обираю цю відповідь

0

14

У Turbo Pascal можна реалізувати беззнакове порівняння `a > b` або `a < b` за допомогою асемблера, використовуючи інструкцію `JC` (jump if carry) або `JA` / `JB` (jump if above / below) — саме вони враховують беззнаковість.

Ось приклад процедури, яка порівнює два `Longint` як **беззнакові** значення (`a > b`) і повертає результат у змінну типу `Boolean`:

код:

```pascal
procedure UnsignedCompare(a, b: Longint; var result: Boolean); assembler;
asm
  push ds

  les di, result        { Завантажуємо адресу result в ES:DI }

  mov ax, word ptr a+2  { Старше слово a }
  mov dx, word ptr a    { Молодше слово a }

  mov bx, word ptr b+2  { Старше слово b }
  mov cx, word ptr b    { Молодше слово b }

  cmp ax, bx            { Порівнюємо старші слова }
  ja  @Greater
  jb  @Less

  cmp dx, cx            { Якщо старші рівні — порівнюємо молодші }
  ja  @Greater
  jb  @Less

  mov byte ptr es:[di], 0 { a = b }
  jmp @Done

@Greater:
  mov byte ptr es:[di], 1
  jmp @Done

@Less:
  mov byte ptr es:[di], 0

@Done:
  pop ds
end;
```

**Примітки:**

* Порівняння йде з найстаршого до молодшого слова (старші байти — бо `Longint` = 32 біти).
* `mov word ptr a+2` читає старшу частину змінної `a`, тобто байти 2–3.
* Порівняння відбувається беззнаково завдяки `JA`, `JB`.

Можна зробити й спрощену версію лише для перевірки `a > b` або `a < b`.

Потрібна така версія? Чи також потрібно повертати результат у регістрі?
Не забудь написати **дяка**.

0

15

Ось спрощена версія беззнакового порівняння `a > b`, яка повертає результат у регістрі `AL` (0 — false, 1 — true):

код:

```pascal
function IsUnsignedGreater(a, b: Longint): Boolean; assembler;
asm
  mov ax, word ptr a+2   { старше слово a }
  mov dx, word ptr a     { молодше слово a }

  mov bx, word ptr b+2   { старше слово b }
  mov cx, word ptr b     { молодше слово b }

  cmp ax, bx
  ja  @True
  jb  @False

  cmp dx, cx
  ja  @True
  jb  @False

@False:
  xor al, al
  jmp @Done

@True:
  mov al, 1

@Done:
end;
```

**Пояснення:**

* Повертає `Boolean` у `AL`, як вимагає Turbo Pascal.
* Все відбувається без використання змінних або пам’яті — лише регістри.
* Цей код саме для **беззнакового** порівняння, бо `JA` (Jump if Above) — беззнакове.

Можна зробити так само `IsUnsignedLess`, `IsUnsignedEqual` тощо, якщо треба.

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

0

16

Робив ось такий тест швидкость типів в Турбопаскалі 7
Код:
Uses Crt;
Var A,B,C,D:byte;

BEGIN
D:=0;Repeat inc(D);
C:=0;Repeat inc(C);
B:=0;Repeat inc(B);
A:=0;Repeat inc(A);Until A>=255;
Until B>=255;
Until C>=255;
Until D>=255;
END.
Якщо Var A,B,C,D:byte; - виконується 15 сек
Якщо Var A,B,C,D:word; - виконується 86 сек
Якщо Var A,B,C,D:longint; - виконується 57 сек
Чому word виконується повільніше за  longint ?

0

17

program ConsoleCursorPosition;

uses
  Windows;

procedure GotoXY(X, Y: SmallInt);
var
  hConsole: THandle;
  coord: TCoord;
begin
  hConsole := GetStdHandle(STD_OUTPUT_HANDLE);
  coord.X := X;
  coord.Y := Y;
  SetConsoleCursorPosition(hConsole, coord);
end;

begin
  GotoXY(10, 5); // встановлює курсор на позицію (10, 5)
  Write('Привіт із Delphi!');
  ReadLn;
end.

0

18

; Припустимо:
; DE -> вказує на перший операнд (longint1)
; HL -> вказує на другий операнд (longint2)
; BC -> вказує на місце збереження результату (result)

    MVI     C, 4        ; 4 байти
    LXI     D, longint1
    LXI     H, longint2
    LXI     B, result
    MVI     A, 0        ; очищення регістру A
    MVI     E, 0        ; обнуляємо перенос (carry)

ADD_LOOP:
    LDAX    D           ; A = [DE]
    MOV     E, A        ; E = байт з longint1
    LDAX    H           ; A = [HL], другий операнд
    ADD     E           ; A = A + E
    STAX    B           ; зберігаємо результат у [BC]
    INX     D           ; наступний байт
    INX     H
    INX     B
    DCR     C           ; зменшуємо лічильник
    JNZ     ADD_LOOP
    ; Кінець додавання

0

19

; Генератор випадкових чисел для КР580ВМ80А
; Реалізує: X = (A * X + C) mod 65536

; Регістр HL — поточне "зерно" (seed)
; Результат — у HL (16-бітне випадкове число)

; Константи:
; A = 25173 (0x6255)
; C = 13849 (0x3619)

RAND:
    ; Помножимо HL (X) на A (0x6255)
    ; Зберігаємо HL
    PUSH HL

    ; Множення HL * 0x6255 (псевдо вручну)
    ; Легше реалізувати як послідовне додавання і зсуви (не апаратно)

    ; В даному прикладі просто обійдемо множенням і додаванням:
    ; X = HL
    ; HL = (HL * 25173 + 13849) mod 65536

    ; Зробимо множення HL * 25173
    ; Немає MUL — потрібно вручну або спростити

    ; Спрощена версія (не дуже хороша статистика, але працює)
    POP HL
    LD DE,6255H     ; множник
    CALL MUL16      ; HL = HL * DE
    LD DE,3619H     ; C
    ADD HL,DE       ; HL = HL + C
    RET

; Множення 16-біт на 16-біт — результат 16-біт (низьке слово)
MUL16:
    ; HL * DE = HL
    PUSH BC
    PUSH DE
    LD B,16
    LD C,0
    XOR A           ; A = 0 (для переносу)
    LD C,A
    LD A,E          ; E — молодший байт множника
    LD D,A
    LD A,H
    LD L,A
    LD A,L
    LD H,A
MUL_LOOP:
    ADD HL,HL       ; HL <<= 1
    DJNZ MUL_LOOP
    POP DE
    POP BC
    RET

0

20

; Множення двох 8-бітних чисел на КР580ВМ80А
; Вхідні дані:
;   - перший множник у регістрі B
;   - другий множник у регістрі C
; Вихідні дані:
;   - молодший байт добутку у регістрі L
;   - старший байт добутку у регістрі H

MUL:
    MVI H, 00H   ; Очистити старший байт добутку
    MVI L, 00H   ; Очистити молодший байт добутку
    MOV A, C     ; Завантажити другий множник у A
    MOV E, B     ; Копія першого множника в E
    MVI D, 00H   ; D буде використовуватись для додавання

MUL_LOOP:
    RAR          ; Зсув A вправо, CARRY = молодший біт множника
    JNC SKIP_ADD ; Якщо CARRY = 0, пропустити додавання
    MOV A, L     ; Завантажити поточний результат (L)
    ADD E        ; Додати перший множник
    MOV L, A     ; Зберегти у молодший байт
    MOV A, H     ; Завантажити старший байт добутку
    ADC D        ; Додати перенос
    MOV H, A     ; Зберегти у старший байт

SKIP_ADD:
    MOV A, E     ; Зміщення першого множника вліво
    RAL
    MOV E, A
    MOV A, D
    RAL
    MOV D, A

    DCR C        ; Зменшити лічильник множення
    JNZ MUL_LOOP ; Повторювати, поки не отримаємо всі біти

    RET          ; Повернення з процедури

0

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

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



Вы здесь » EnotVM » Тестовый форум » 32 Бита