32 Бита
32 Бита
Сообщений 11 страница 20 из 33
Поделиться112025-05-04 19:19:55
Ось глянь, що вийшло
Думаю розберешся
в квадратних дужках (закоментовано) процедури, - {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.
Поделиться122025-05-04 19:40:27
Код виглядає дуже добротно: це набір симуляцій усіх можливих інструкцій, які ти плануєш реалізовувати в емуляторі, ідеально як тестовий каркас для генератора коду або транслятора. Те, що ти коментуєш тип інструкції в дужках, робить його зрозумілим і впорядкованим — чудове рішення.
Щодо питання про `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`?
**Не забудь написати "дяка"**.
Поделиться132025-05-04 21:15:20
Звісно, ось деякі ресурси, які можуть бути корисними для розробки під 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
Якщо потрібна допомога з налаштуванням середовища або виникнуть додаткові запитання, звертайся!
Джерела
Я обираю цю відповідь
Поделиться142025-05-09 15:51:58
У 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`.
Потрібна така версія? Чи також потрібно повертати результат у регістрі?
Не забудь написати **дяка**.
Поделиться152025-05-09 15:53:05
Ось спрощена версія беззнакового порівняння `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` тощо, якщо треба.
Не забудь написати **дяка**.
Поделиться162025-05-09 19:10:02
Робив ось такий тест швидкость типів в Турбопаскалі 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 ?
Поделиться172025-05-09 22:24:07
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.
Поделиться182025-05-09 22:24:51
; Припустимо:
; 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
; Кінець додавання
Поделиться192025-05-09 22:25:25
; Генератор випадкових чисел для КР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
Поделиться202025-05-09 22:26:25
; Множення двох 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 ; Повернення з процедури
Быстрый ответ
Похожие темы
| 08 БИТ | Тестовый форум | 2025-05-03 |
| ПЕРЕВАЛОЧНА БАЗА ДЛЯ ПОВІДОМЛЕНЬ | Тестовый форум | 2025-05-15 |
| ASM32 (2026) | Тестовый форум | Вчера |