Форум программистов, компьютерный форум, киберфорум
Наши страницы
Assembler, MASM, TASM
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.50/4: Рейтинг темы: голосов - 4, средняя оценка - 4.50
AIRWALK
0 / 0 / 0
Регистрация: 07.03.2010
Сообщений: 19
1

Преобразование кода в FASM

15.05.2012, 14:52. Просмотров 803. Ответов 6
Метки нет (Все метки)

Имеется код текстового редактора. Нужно данный код преобразовать в FASM, чтоб нормально запускался и компилировался. Заранее благодарен.

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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
 .model small, C ;модель памяти + соглашение о передаче параметров
 .286   ;чтобы можно было посылать в стек числа
 .code   ;сегмент кода
 .startup  ;точка входа
 call init  ;инициализация
 call PrWin, 0, 0, XSize, YSize, DOUBLE, MainColor ;рисуем окно с рамкой
 call PrHelpMess ;выводим строку "F1 - помощь"
 
 call SetCursor ;установим курсор в позицию (1,1)
 call GetFile  ;читаем файл, если имя файла задано параметром
 
Redraw:    ;сюда приходим, когда надо перерисовать содержимое буфера
 call SetName  ;пишем имя файла
 
 mov ax, XSize ;выводим содержимое буфера на экран
 dec ax
 mov cx, YSize
 dec cx
 mov dx, UpLine
 push ds
 mov ds, FileSeg
 call PrText, 1, 1, ax, cx, dx
 pop ds
 
NewCursor:   ;сюда приходим, когда надо только поменять позицию курсора
 call SetCursor
KeyLoop:   ;цикл ожидания нажатия на клавишу
 mov ah,0  ;al=кон, ah=скан-код
 int 16h
 
 lea di, KeyTable ;адрес таблицы отрабатываемых кодов
 mov cx, KeyTableLen ;длина
SearchKey_loop:
 cmp ah, [di] ;сравниваем скан-код
 je KeyFound ;нашли код
 inc di
 loop SearchKey_loop ;по всей таблице
    ;дальше нас интересуют только символьные коды
 cmp al, \' \'  ;управляющие игнорируем
 jae KeyInsert ;вставляем код
 jmp KeyLoop
KeyFound:   ;отработка кода
 sub di, offset KeyTable
 shl di, 1  ;di - смещение в таблице PrgTable
 jmp PrgTable[di] ;на отработку
 
KeyInsert:   ;вставка символа
 cmp FileLen, 0ffffh ;проверка на длину (макс = 0ffffh)
 je KeyLoop
 mov fChange, 1 ;содержимое поменялось
    ;освободим места для нового символа, для этого сдвинем на 1 байт
 mov si, FileLen ;смещение конца
 lea di, [si+1] ;на 1 дальше
 xor bx, bx
 mov bl, XFile ;позиция в текущей строке
 add bx, CurLine ;+смещение строки в файле (смещение, куда надо вставить)
 mov cx, di
 sub cx, bx  ;количество копируемых байт
 push ds es
 mov es, FileSeg
 mov ds, FileSeg ;в рабочем буфере
 std   ;в обратном порядке
 rep movsb  ;копируем
 cld   ;воостановим прямой порядок цепочечных команд
 mov [bx], al ;вставляем введенный код на его место
 pop es ds
 inc FileLen  ;инкремент длины файла
 call PressedKeyRight ;перемещаем курсор вправо
 jmp Redraw  ;не перерисовку
KeyEnter:   ;вставка перевода строки, а точнее двух кодов 0dh и 0ah
 cmp FileLen, 0fffeh ;проверка на длину (макс = 0fffeh)
 jae KeyLoop
 mov fChange, 1 ;содержимое поменялось
    ;освободим места для двух символов, для этого сдвинем на 2 байта
 mov si, FileLen ;смещение конца
 lea di, [si+2] ;на 2 дальше
 xor bx, bx
 mov bl, XFile ;позиция в текущей строке
 add bx, CurLine ;+смещение строки в файле (смещение, куда надо вставить)
 mov cx, di
 sub cx, bx  ;количество копируемых байт
 push ds es
 mov es, FileSeg
 mov ds, FileSeg ;в рабочем буфере
 std   ;в обратном порядке
 rep movsb  ;копируем
 cld   ;воостановим прямой порядок цепочечных команд
 mov word ptr [bx], 0a0dh ;вставляем введенные коды на их место
 pop es ds
 add FileLen, 2 ;увеличиваем длину файлу
 call PressedKeyRight ;перемещаем курсор вправо
to_Redraw:   ;промежуточная метка, чтобы достать до метки < 128
 jmp Redraw  ;не перерисовку
to_KeyLoop:   ;промежуточная метка, чтобы достать до метки < 128
 jmp KeyLoop
finish:    ;выход
 call exit
KeyUp:
 call PressedKeyUp ;стрелка вверх
 jc to_KeyLoop ;ничего дополнительного не делать
 jz to_Redraw ;перерисовать
 jmp NewCursor ;поменять позицию курсора
KeyLeft:   
 call PressedKeyLeft ;стрелка влево
 jc to_KeyLoop
 jz to_Redraw
 jmp NewCursor
KeyRight:
 call PressedKeyRight ;стрелка вправо
 jc to_KeyLoop
 jz to_Redraw
 jmp NewCursor
Keydown:
 call PressedKeyDown ;стрелка вниз
 jc to_KeyLoop
 jz to_Redraw
 jmp NewCursor
KeyHelp:
 call Help  ;F1
to_NewCursor:
 jmp NewCursor
KeyRead:
 call ReadFile ;F3
 jc to_NewCursor
 jmp Redraw
KeyWrite:
 call WriteFile ;F2
 jc to_NewCursor
 jmp Redraw
KeyBack:
 call BackSpace ;BackSpace
 jc to_KeyLoop
 jmp Redraw
 
;расчет позиции курсора для строки текста, учитывается табуляция
;bx - до какой позиции смотрим
CalcXtab proc
 push ds
 xor cx, cx  ;счетчик позиции на экране
 mov si, CurLine ;текущая строка 
 mov ds, FileSeg
 dec bx  ;адрес предыдущего байта
CX_loop:
 cmp si, bx  ;дошли до bx
 jge CX_ret  ;на выход, в CX искомая позиция курсора
 lodsb   ;очередной байт
 inc cx  ;посчитаем
 cmp al, 9  ;табуляция?
 jne CX_loop  ;для обычного символа просто идем на следующий
 mov ax, cx  ;табуляцию расширяем до 8-й позиции
 and ax, 7  ;ax = x mod 8
 sub ax, 8
 neg ax  ;ax = 8 - (x mod 8)
 add cx, ax  ;ax - число пробелов, чтобы табуляция встала на позиции, кратной 8
 jmp CX_loop  ;продолжаем
CX_ret:
 mov ax, cx
 pop ds
 mov XScreen, al ;сохраним новую позицию курсора
 ret
CalcXtab endp
 
;расчет позиции курсора для строки текста, учитывается табуляция
;отличие от предыдузей в том, что здесь проверяем на старую позицию курсора
;используется в переходе на строку вниз/вверх
CalcXXtab proc
 push ds
 mov dl, XScreen ;старая позиция курсора
 mov si, CurLine ;текущая строка 
 mov ds, FileSeg
 xor bx, bx  ;индекс в текущей строке
 xor cx, cx  ;сl-текущая позиция в строке, ch-промежуточное значение позиции
CXX_loop:
 cmp ch, dl  ;дошли до старой позиции
 ja CXX_ret1
 mov cl, ch  ;нет, сохраним, как текущую
 mov al, [bx+si] ;читаем байт
 cmp al, 0dh  ;конец строки?
 je CXX_ret  ;да, это и будет новая позиция на экране
 cmp al, 9  ;табуляция?
 jne CXX_next ;нет - на следующий
 mov al, cl  ;расширяем табуляцию пробелами
 and al, 7
 sub al, 7
 sub ch, al
CXX_next:
 inc ch  ;инкремент позиции на экране
 inc bx  ;инкремент позиции в файле
 jmp CXX_loop
CXX_ret1:
 dec bl  ;в случае, когда табуляция перескакивает, то на 1 меньше
CXX_ret:
 pop ds
 mov XFile, bl ;сохраним позицию в файле
 mov XScreen, cl ;и на экране
 ret
CalcXXtab endp
 
;отработка клавиши "влево"
PressedKeyLeft proc
 mov ax, CurLine ;в первой позиции ничего не делаем
 or ax, UpLine
 or al, XFile
 jnz KL_Change 
KL_NoChange:
 stc
 ret
KL_Change:
 xor ax, ax
 mov al, XFile
 add ax, CurLine ;ax - позиция текущего символа в файле
 push ds
 mov ds, FileSeg
 mov bx, ax
 mov dl, [bx-1] ;предыдущий символ
 pop ds
 
 cmp dl, 0ah  ;мы в начале строки?
 je KL_eol  ;становимся в конец предыдущей
 dec XFile  ;уменьшаем на 1 позицию в строке
 cmp dl, 9  ;предыдущий символ - табуляция?
 je KL_tab  ;отрабатываем
 dec XScreen  ;для обычного символа просто уменьшаем позицию на экране
KL_NewCursor:
 or al, 1  ;Z=0 для установки курсора
 clc   ;для отработки
 ret
KL_tab:
 call CalcXtab ;посчитаем новую позицию курсора на экране
 jmp KL_NewCursor
KL_eol:    ;переходим в конец строки выше
 push ds
 mov ds, FileSeg
 dec bx  ;bx - позиция в файле символа 0ah
 
 lea di, [bx-1] ;di - позиция 0dh
KL_eol_loop:   ;ищем начало строки
 dec bx  ;на предыдущий символ
 test bx, bx  ;для первой строки дойдем до 0
 jz KL_set_CurLine ;начало первой строки
 mov al, [bx] ;читаем символ
 cmp al, 0ah  ;0ah?
 jne KL_eol_loop
 inc bx  ;нашли 0ah, следующий - начало строки
KL_set_CurLine:
 pop ds
 
 mov CurLine, bx ;сохраним адрес, как адрес текущей строки
 
 mov bx, di  ;посчитаем позицию на экране
 sub bx, CurLine ;bx - длина строки
 mov XFile, bl ;запомним, как позицию в строке файла
 lea bx, [di+1] ;адрес конца строки
 call CalcXtab ;считаем позицию на экране
 
KL_scroll:   ;если есть необходимость, делаем скроллинг на одну строку
 dec YFile  ;уменьшим номер строки в файле
 sub YScreen, 1 ;уменьшим номер строки на экране 
    ;(отнимаем 1, а не dec - чтобы отработался флаг С)
 jge KL_NewCursor ;если нет необходимости скроллировать, то выходим
 
 mov ax, CurLine ;устанавливаем новый адрес начала прорисовки
 mov UpLine, ax
 mov YScreen, 0 ;номер строки на экране = 0
 
 mov ax, 0701h ;скролинг на одну строку вниз
 mov cx, 0101h ;с позиции (1,1)
 mov dl, byte ptr XSize ;и все, что внутри рамки
 mov dh, byte ptr YSize
 sub dx, cx
 mov bh, byte ptr MainColor ;цвет фона
 int 10h
 mov ax, XSize ;выводим в первую строку экрана текущую строку файла
 dec ax
 mov dx, UpLine
 push ds
 mov ds, FileSeg
 call PrText, 1, 1, ax, 1, dx
 pop ds
 jmp KL_NewCursor
PressedKeyLeft endp
 
;строка вверх
PressedKeyUp proc
 mov ax, CurLine ;для первой строки ничего не делаем
 or ax, UpLine
 jnz KU_Change 
KU_NoChange:
 stc
 ret
KU_Change:
 mov bx, CurLine ;начало текущей строки в файле
 
 push ds
 mov ds, FileSeg
 dec bx  ;адрес 0ah предыдущей строки
    ;ищем начало предыдущей строки
KU_eol_loop:
 dec bx
 test bx, bx  ;для первой строки начало - bx=0
 jz KU_set_CurLine
 mov al, [bx] ;ищем начало строки, как адрес байта, 
 cmp al, 0ah  ; следующего за 0ah (строки, которая выше)
 jne KU_eol_loop
 inc bx  ;начало строки
KU_set_CurLine:
 pop ds
 mov CurLine, bx ;сохраним
 
 call CalcXXtab ;вычислим текущую позицию на экране
 
 jmp KL_scroll ;проскроллируем, если необходимо
 
PressedKeyUp endp
 
;отработка клавиши "вправо"
PressedKeyRight proc
 xor ax, ax  ;если в позиции последнего символа,
 mov al, XFile ; то ничего не делаем
 add ax, CurLine
 cmp ax, FileLen
 jb KR_Change
KR_NoChange:
 stc
 ret
KR_Change:
 push ds
 mov ds, FileSeg
 mov bx, ax
 mov dl, [bx] ;символ в текущей позиции
 pop ds
 
 cmp dl, 0dh  ;конец строки?
 je KR_eol  ;да, переходим на следующую
 inc XFile  ;нет, инкремент позиции в строке файла
 cmp dl, 9  ;если табуляция,
 je KR_tab  ;то посчитать позицию на экране
 inc XScreen  ;нет, просто инкремент позиции на экране
KR_NewCursor:
 or al, 1  ;смена позиции курсора
 clc   ;отработать
 ret
KR_tab:    ;табуляция
 xor ax, ax
 mov al, XScreen
 and ax, 7
 sub ax, 8  ;ax = (XScreen mod 8) - 8 < 0
 sub XScreen, al ;выравнять до позиции, кратной 8
 jmp KR_NewCursor
KR_eol:    ;переходим на следующую строку
 xor ax, ax
 mov al, XFile
 add ax, CurLine
 inc ax  ;обойдем 0dh, 0ah
 inc ax
 
 mov CurLine, ax ;сохраним адрес, как начало новой строки
 
 mov XFile,0  ;начало строки в файле
 mov XScreen, 0 ;начало строки на экране
 
KR_scroll:   ;скроллинг на одну строку вниз, если необходимо
 inc YFile  ;инкремент строки в файле
 inc YScreen  ;инкрмент строки на экране
 xor ax, ax
 mov al, YScreen ;номер строки на экране
 mov cx, YSize
 dec cx  ;максимальный номер строки + 1
 cmp ax, cx  ;если меньше то скроллировать не надо
 jb KR_NewCursor
 dec YScreen  ;вернем на номер последней строки
    ;найдем адрес второй строки для отображения
 mov bx, UpLine ;адрес первой строки на экране
 push ds
 mov ds, FileSeg
KR_eol_loop:   ;ищем 0ah в конце строки
 mov al, [bx] 
 inc bx
 cmp al, 0ah
 jne KR_eol_loop
 pop ds
 mov UpLine, bx ;сохраним следующий адрес, как адрес верхней строки
 
 mov ax, 0601h ;скроллируем на одну строку вверх
 mov cx, 0101h
 mov dl, byte ptr XSize
 mov dh, byte ptr YSize
 sub dx, cx
 mov bh, byte ptr MainColor
 int 10h
 mov ax, XSize
 dec ax
 mov cx, YSize
 dec cx
 mov dx, CurLine
 push ds
 mov ds, FileSeg ;выводим одну текущую строку в конце экрана
 call PrText, 1, cx, ax, 1, dx
 pop ds
 jmp KR_NewCursor
PressedKeyRight endp
 
;строка вниз
PressedKeyDown proc
 mov bx, CurLine ;пробуем найти 0ah, если не находим, то
KD_eol_loop:   ; то ничего не делаем
 cmp bx, FileLen
 jae KD_NoChange
 push ds
 mov ds, FileSeg
 mov al, [bx] 
 pop ds
 inc bx
 cmp al, 0ah
 jne KD_eol_loop
 jmp KD_Change
KD_NoChange:
 stc
 ret
KD_Change:
 mov CurLine, bx ;сохраняем адрес байта за 0ah, 
    ; как адрес текущей строки
 call CalcXXtab ;посчитаем позицию на экране для новой строки
 
 jmp KR_scroll ;на скроллирование, если надо
 
PressedKeyDown endp
 
;отработка BackSpace
BackSpace proc
 mov ax, CurLine ;для первого символа ничего не делаем
 or ax, UpLine
 or al, XFile
 jnz BS_Change
BS_NoChange:
 stc
 ret
BS_Change:
 mov fChange, 1 ;содержимое изменено
 call PressedKeyLeft ;курсор влево
 xor bx, bx
 mov bl, XFile
 add bx, CurLine ;текущая позиция в файле
 push ds  ;копируем на 1 или на 2 позиции, затирая текущий символ
 push es
 mov es, FileSeg
 mov ds, FileSeg
 mov di, bx
 mov bx, 1  ;для обычного символа 
 mov al, [di]
 cmp al, 0dh
 jne copy_back
 inc bx  ;для конца строки bx = 2
copy_back:
 lea si, [di+bx] ;адрес, откуда пишем
 mov cx, ss:Filelen
 sub cx, si
 inc cx  ;число копируемых байт (вместе с завершающим 0)
 rep movsb  ;копируем
 pop es
 pop ds
 dec di
 mov FileLen, di ;новая длина файла
 clc   ;для прорисовки
 ret
BackSpace endp
 
;рисуем окно (x1,y1)-(x2,y2) с двойной/одинарной рамкой и указанным цветом
PrWin proc x1:word, y1:word, x2:word, y2:word, TableType:word, color:word
local rows:word, cols:word
 
 mov ax, 0600h ;очищаем окно
 mov ch, byte ptr y1
 mov cl, byte ptr x1 
 mov dh, byte ptr y2
 mov dl, byte ptr x2 
 mov bh, byte ptr color
 int 10h
 
 mov si, TableType ;тип рамки (0,1)
 shl si, 1
 mov si, Borders[si] ;адрес таблицы псевдографики
 
 mov ax, Xsize ;вычисляем адрес начала вывода
 inc ax
 mul y1
 add ax, x1
 shl ax, 1
 mov di, ax  ;адрес вывода в видеобуфер
 
 mov ax, y2  ;число строк
 sub ax, y1
 inc ax
 mov rows, ax
 
 mov ax, x2  ;число колонок
 sub ax, x1
 inc ax
 mov cols, ax
 
 mov bx, XSize
 inc bx
 shl bx, 1  ;длина строки для перехода на следующую строку
 
 mov ah, byte ptr color+1 ;цвет рамки
 push di
 mov al, LU[si] ;левый верхний уголок
 stosw
 mov cx, cols ;горизонталь
 dec cx
 dec cx
 mov dx, cx  ;сохраним "внутренюю" длину колонок
 mov al, HH[si]
 rep stosw
 mov al, RU[si] ;правый верхний уголок
 stosw
 pop di
 add di, bx
 mov cx, rows
 dec cx
 dec cx  ;число "средних" строк
PW_RLoop:   ;окаймим "средние" строки вертикалями
 push di
 mov al, VV[si]
 stosw
 add di, dx
 add di, dx
 stosw
 pop di
 add di, bx
 loop PW_RLoop
 mov al, LD[si] ;нижняя часть, левый нижний уголок
 stosw
 mov cx, dx
 mov al, HH[si] ;горизонталь
 rep stosw
 mov al, RD[si] ;правый нижний уголок
 stosw
 
 ret
PrWin endp 
 
;Установка курсора
SetCursor proc
 push ax
 mov ah, 2
 mov dx, word ptr ss:XScreen ;x+y
 add dx, 0101h ;поправка на позицию (1,1)
 mov bh, 0
 int 10h
 pop ax
 ret
SetCursor endp
 
;начальная инициализация
init proc
 call GetParm  ;вводим имя файла из строки параметров
 
;узнаем размер экрана по горизонтали
 mov ah, 0fh 
 int 10h
 mov al, ah  ;в ah - число текстовых колонок
 mov ah, 0
 dec ax
 mov Xsize, ax ;сохраним индекс последнего символа в строке экрана
 
;определим высоту экрана
 mov ax, 1130h
 int 10h
 mov al, dl  ;в dl число строк - 1
 mov ah, 0
 mov Ysize, ax ;сохраним индекс последней строки экрана
 
;обнулим некоторые переменные
 mov fChange, 0
 mov CurLine, 0
 mov UpLine, 0
 mov XScreen, 0
 mov YScreen, 0
 mov XFile, 0
 mov YFile, 0
 
;зададим адрес сегмента для содержимого файла, как DS+1000h
 xor bx, bx
 mov ax, ds
 add ax, 1000h
 mov FileSeg, ax
 mov FileLen, bx ;длины 0
 push ds
 mov ds, ax
 mov [bx], bl ;первый символ - 0
 pop ds
 
;запомним позицию курсора
 mov ah, 3
 mov bh, 0
 int 10h
 mov PosOld, dx
 
;сохраним содержимое видеостраницы, чтобы потом восстановить
 mov ax, XSize
 mov cx, YSize
 inc ax
 inc cx
 mul cx
 mov cx, ax
 push ds
 push ds
 pop es
 mov ax, 0b800h
 mov ds, ax
 lea di, SaveScr
 xor si, si
 rep movsw
 pop ds
 
;настраиваем сегментный регистр es на видеобуфер
 mov ax, 0b800h
 mov es, ax
 ret
init endp
 
;рассматриваем строку параметров, как имя файла
GetParm proc
 mov si, 81h  ;начало строки, длину по адресу 80h игнорируем, 
    ; будем искать конец по 0dh
 lea di, FName ;сюда запишем имя файла
GPSpaceLoop:   ;сначала пропустим разделители перед параметром
 mov al,es:[si] ;es адресует PSP
 inc si
 cmp al, 0dh
 je GPRet  ;параметра нет
 cmp al, \' \'
 je GPSpaceLoop
 cmp al, 9
 je GPSpaceLoop
GPName:    ;что-то нашли
 mov [di], al ;сохраняем
 inc di
 mov al,es:[si] 
 inc si
 cmp al, 0dh  ;продолжаем до 0dh
 je GPRet
 cmp al, \' \'  ; или до разделителя
 je GPRet
 cmp al, 9
 jne GPName
GPret:
 mov byte ptr [di], 0;закрываем строку нулем
 ret
GetParm endp
 
;пишем имя файла вверху экрана
SetName proc
 mov cx, XSize
 sub cx, 4  ;на всякий случай, ограничим длину
 lea si, FName ;имя файла
 cmp byte ptr [si],0 ;задано ли?
 jne SNPrName
 lea si, Default ;нет - считаем именем Default.txt
SNPrName:
 mov di, 2  ;с позиции 1
 mov ah, byte ptr MainColor+1 ;цвет
 mov al, \' \'  ;отделим пробелом
 stosw
SNPrLoop:
 lodsb
 cmp al, 0
 je SNPrTail
 stosw
 loop SNPrLoop ;выведем строку имени
SNPrTail:
 mov al, \' \'
 stosw   ;пробел
 dec cx
 mov al, BorderDouble + HH
 stosw
 dec cx
 cmp fChange, 0
 je SNFlagChange
 mov al, \'*\'  ;признак изменения содержимого (* или черточка)
SNFlagChange:
 stosw
 dec cx  ;до конца, чтобы вытереть возможное старое, выведем черточки
 jcxz SNRet
 mov al, BorderDouble + HH
SN_clear_loop:
 stosb
 inc di
 loop SN_clear_loop
SNRet:
 ret
SetName endp
 
;краткая помощь
;внутри 11 строк
Help proc
 call MessageBox, offset sHelp, 11
 ret
Help endp
 
;читаем файл по F3
ReadFile proc
 cmp fChange, 0 ;было ли изменение?
 je RFContinue
;1 строку сообщения
 call MessageBox, offset sChanged, 1
;возвращается скан-код нажатой клавиши
 cmp ah, 15h  ;Y
 jne RFRet  ;не Y - не сохраняем
RFContinue:
;запрос имени файла
 call NameBox,offset sReadFile, offset sFileName, offset FName
 jc RFRet  ;Esc - отказ от чтения
 call GetFile  ;читаем файл с именем FName
 mov fChange, 0 ;все обнуляем
 mov CurLine, 0
 mov UpLine, 0
 mov XScreen, 0
 mov YScreen, 0
 mov XFile, 0
 mov YFile, 0
 clc   ;перерисовываем
 ret
RFRet:
 stc
 ret
ReadFile endp
 
;пишем файл по F2
WriteFile proc
;запрос имени файла
 call NameBox,offset sWriteFile, offset sFileName, offset FName
 jc WFRet  ;отказ по Esc
 call SetFile  ;сохраняем файл
 mov fChange, 0 ;сброс флага изменения
 clc   ;перерисуем
WFRet:
 ret
WriteFile endp
 
;читаем файл
GetFile proc
 lea dx, FName
 cmp FName, 0
 jnz GFOpen
 lea dx, default
GFOpen:
 mov si, dx  ;сохраняем адрес имени (для сообщений)
 mov ax, 3d00h
 int 21h  ;открываем на чтение
 jc GFOpenError ;ошибка открытия
 mov bx, ax  ;описатель файла
 push ds
 mov ds, FileSeg
 xor dx, dx
 mov cx,0ffffh
 mov ah, 3fh
 int 21h  ;читаем в сегмент данный файла
 jc GFReadError ;ошибка чтения
 cmp ax, cx  ;проверим размер файла (еще есть что читать, значит больше, чем надо)
 jz GFSizeError ;выведем ошибку
 mov si, ax  ;длина как индекс конца
 mov byte ptr [si],0 ;запишем в конце нолик
 pop ds
 mov FileLen, ax ;сохраним длину файла
 
 mov fChange, 0 ;сбросим флаг изменения
FNCloseFile:
 mov ah, 3eh
 int 21h  ;закрываем файл
 ret
;сообщения об ошибках
GFOpenError:
 cmp si, offset default
 je GFRet  ;ошибку открытия файла default.txt не выводим
 call ErrorBox, offset sOpenError, si
GFRet:
 ret
GFReadError:
 pop ds
 call ErrorBox, offset sReadError, si
 jmp FNCloseFile
GFSizeError:
;поместим в начало байт 0 и сбросим длину в 0
 mov byte ptr ds:[0],0
 pop ds
 mov FileLen, 0
 call ErrorBox, offset sSizeError, si
 jmp FNCloseFile
GetFile endp
 
;запись файла
SetFile proc
 lea dx, FName
 cmp FName, 0
 jnz SFOpen
 lea dx, default
SFOpen:
 mov si, dx  ;сохраним имя (для сообщений)
 mov ah, 3ch  ;создаем файл (если был с таким именем, то тот потеряется)
 xor cx, cx
 int 21h
 jc SFCreateError
 mov bx, ax  ;описатель файла
 mov cx, FileLen ;длина файла
 push ds
 mov ds, FileSeg
 xor dx, dx
 mov ah, 40h  ;пишем в файл с адреса ds:dx
 int 21h
 pop ds
 jc SFWriteError
 
 mov fChange, 0 ;сбросим флаг изменения
SFCloseFile:
 mov ah, 3eh
 int 21h  ;закрываем файл
 ret
;сообщения об ошибках
SFCreateError:
 call ErrorBox, offset sCreateError, si
SFRet:
 ret
SFWriteError:
 call ErrorBox, offset sWriteError, si
 jmp SFCloseFile
SetFile endp
 
;сообщение об ошибке (всегда две внутренние строки)
;sFormat - форматная строка, параметром можно указать %, в то место вставится sStr
;sStr - имя файла, вставляемое, как параметр в сообщение
;во второй строке всегда пишем: "Нажмите на любую клавишу"
ErrorBox proc sFormat:word, sStr:word
local sTextBuffer:byte:76,  \ ;буфер для формирования строки
 wSave:word:80*4,  \ ;для сохранения старого содержимого экрана
 MB_x1:word, MB_y1:word, MB_x2:word, MB_y2:word ;координаты окна (псевдографики)
 
;посчитаем размеры окна, для этого найдем максимальную длину строки
 xor dx, dx  ;максимальная длина
 mov si, sFormat ;форматная строка
 lea di, sTextBuffer ;где формируем данные для вывода
 xor cx, cx  ;длина первой строки
EBForm:
 lodsb
 cmp al, 0
 je EBSecond ;добавляем вторую строку
 cmp al, \'%\'
 je EBParm  ;добавляем параметр
 mov [di], al ;сохраняем
 inc di
 cmp al, \' \'  ;0dh,0ah не считаем
 jb EBForm
 inc cx  ;считаем символы
 jmp EBForm
EBParm:    ;копируем параметр
 push si
 mov si, sStr
EBParmLoop:
 lodsb
 cmp al, 0
 je EBParmEnd
 inc cx  ;считаем длину строки
 mov [di], al
 inc di
 jmp EBParmLoop
EBParmEnd:
 pop si
 jmp EBForm  ;продолжаем проссматривать форматную строку
EBSecond:
 cmp cx, dx  ;сравниваем с максимумом
 jbe EBAnyKey
 mov dx, cx
EBAnyKey:   ;добавляем строку sAnyKey
 xor cx, cx
 lea si, sAnyKey
EBAnyLoop:
 lodsb
 cmp al, 0
 je EBCalcSize ;конец
 mov [di], al
 inc di
 cmp al, \' \'
 jb EBAnyLoop
 inc cx  ;считаем
 jmp EBAnyLoop
EBCalcSize:
 cmp cx, dx  ;ищем максимум
 ja EBCalcMiddle
 mov cx, dx
EBCalcMiddle:
 add cx, 4  ;+ по пробелу и чертечке слева и справа
 mov ax, XSize ;сделаем, чтобы окно было посередине экрана
 sub ax, cx
 shr ax, 1
 mov MB_x1, ax ;Х левого верхнего угла
 add ax, cx
 dec ax
 mov MB_x2, ax ;Х правого нижнего угла
 mov ax, YSize
 sub ax, 4
 shr ax, 1
 mov MB_y1, ax ;Y левого верхнего угла
 add ax, 3  ;внутри 2 строки
 mov MB_y2, ax ;Y правого нижнего угла
 
 lea di, wSave ;сохраняем старое содержимое экрана
 mov cx, XSize ; причем для простоты сохраняем строки от начала до конца
 mov ax, MB_y1
 mul cx
 shl ax, 1
 mov si, ax
 shl cx, 2
 push ds
 push es
 push ds
 push es
 pop ds
 pop es
 rep movsw
 pop es
 pop ds
 
;рисуем окно с рамкой с цветом ошибок
 call PrWin, MB_x1, MB_y1, MB_x2, MB_y2, SINGLE, ErrorColor
;и выводим текст из 2-х строк в позицию (1,1)
 mov ax, MB_x1
 inc ax
 inc ax
 mov cx, MB_y1
 inc cx
 mov dx, MB_x2
 sub dx, ax
 lea bx, sTextBuffer
 call PrText, ax, cx, dx, 2, bx
 
 push word ptr XScreen ;сохраняем позицию курсора
 mov ax, MB_x2  ;установим курсор в конец второй строки
 sub al, 2
 mov XScreen, al
 mov ax, MB_y2
 sub al, 2
 mov YScreen, al
 call SetCursor
 
 mov ah, 0   ;ждем нажатие на клавишу
 int 16h
 
 lea si, wSave  ;востановим экран
 mov cx, XSize
 mov ax, MB_y1
 mul cx
 shl ax, 1
 mov di, ax
 shl cx, 2
 rep movsw
 
 pop word ptr XScreen ;восстановим курсор
 call SetCursor
 ret
ErrorBox endp
 
;вывод сообщения с получением кода нажатой клавиши
;sStr - выводимое сообщение
;nRows - число информационных строк
MessageBox proc sStr:word, nRows:word
local wSave:word:80*14,  \;для сохранения старого содержимого (максимум 12 инфо строк)
 MB_x1:word, MB_y1:word, MB_x2:word, MB_y2:word ;координаты окна
 
;найдем максимальную длину строки
 mov si, sStr
 xor cx, cx  ;текущая
 mov dx, cx  ;максимальная
MBStrLen:
 lodsb
 cmp al, 0ah
 je MB_EOL
 cmp al, 0
 je MBCmpLastPart
 cmp al, \' \'
 jb MBStrLen
 inc cx
 jmp MBStrLen
MB_EOL:
 cmp cx, dx
 jbe to_MBStrLen
 mov dx, cx
to_MBStrLen:
 xor cx, cx
 jmp MBStrLen
MBCmpLastPart:
 cmp cx, dx
 ja MBCalcMiddle
 mov cx, dx
MBCalcMiddle:   ;посчитаем Xи Y, чтобы было в центре экрана
 add cx, 4  ;добавим два пробела и две черточки
 mov ax, XSize
 sub ax, cx
 shr ax, 1
 mov MB_x1, ax ;Х левого верхнего угла
 add ax, cx
 dec ax
 mov MB_x2, ax ;Х правого нижнего угла
 mov ax, YSize
 sub ax, nRows ;инфо строки
 sub ax, 2  ;верхняя и нижняя
 shr ax, 1
 mov MB_y1, ax ;Y левого верхнего угла
 add ax, nRows
 inc ax
 mov MB_y2, ax ;Y правого нижнего угла
 
 lea di, wSave ;сохраним экран
 mov cx, XSize
 inc cx
 mov ax, MB_y1
 mul cx
 shl ax, 1
 mov si, ax
 mov ax, nRows
 add ax, 2
 mul cx
 mov cx, ax
 push ds
 push es
 push ds
 push es
 pop ds
 pop es
 rep movsw
 pop es
 pop ds
 
;нарисуем окно с рамкой
 call PrWin, MB_x1, MB_y1, MB_x2, MB_y2, SINGLE, MessageColor
;выведем текст в позицию (2,1)
 mov ax, MB_x1
 inc ax
 inc ax
 mov cx, MB_y1
 inc cx
 mov dx, MB_x2
 sub dx, ax
 call PrText, ax, cx, dx, nRows, sStr
 
 push word ptr XScreen ;сохраним курсор
 mov ax, MB_x2  ;курсор в конец последней инфо строки
 sub al, 2
 mov XScreen, al
 mov ax, MB_y2
 sub al, 2
 mov YScreen, al
 call SetCursor
 
 mov ah, 0
 int 16h   ;ждем
 
 push ax   ;сохраним код!
 lea si, wSave  ;востановим старое содержимое экрана
 mov cx, XSize
 inc cx
 mov ax, MB_y1
 mul cx
 shl ax, 1
 mov di, ax
 mov ax, nRows
 add ax, 2
 mul cx
 mov cx, ax
 rep movsw
 pop ax   ;восстановим и вернем код нажатой клавиши!
 
 pop word ptr XScreen ;восстановим позицию курсора
 ret    ;установится в сновном цикле!
MessageBox endp
 
;вывод сообщения и запрос имени файла
;sTitle - первая строка сообщения
;sName - строка "Имя файла:"
;sOldName - адрес строки со старым именем и куда будет это имя потом записано
NameBox proc sTitle:word, sName:word, sOldName:word
local sTextBuffer:byte:76,  \;для формирования строки для вывода
 wSave:word:80*4,  \;для сохранения экрана
 MB_x1:word, MB_y1:word, MB_x2:word, MB_y2:word ;позиция окна
local offName:word,   \;смещение вводимого имени в строке sTextBuffer
 lenName:word,   \;длина собственно имени файла
 lenStr:word  ;длина строки sName
 
 xor dx, dx  ;ищем максимальную длину строки
 mov si, sTitle ;начинаем с первой
 lea di, sTextBuffer ;и формируем строку в sTextBuffer
 xor cx, cx
NBForm:
 lodsb
 cmp al, 0
 je NBAddName
 mov [di], al
 inc di
 cmp al, \' \'
 jb NBForm
 inc cx
 jmp NBForm
NBAddName:   ;добавляем sName
 mov dx, cx
 xor cx, cx
 mov lenStr, cx ;считаем ее длину
 mov si, sName
NBNameLoop:
 lodsb
 cmp al, 0
 je NBOldName
 mov [di], al
 inc di
 cmp al, \' \'
 jb NBNameLoop
 inc cx
 inc lenStr
 jmp NBNameLoop
NBOldName:
 add cx, 12  ;12 позиций на имя 8.3 !
 
 mov offName, di ;начало имени файла
 mov lenName, 0 ;длина имени
 
 mov si, sOldName ;перенесем старое имя
 cmp byte ptr [si], 0
 jne NBCopyName
 lea si, Default
NBCopyName:
 lodsb
 cmp al, 0
 je NBCalcSize
 mov [di], al
 inc di
 inc lenName
 jmp NBCopyName
NBCalcSize:
 mov [di], al ;закрываем нулем
 
 cmp cx, dx
 ja NBCalcMiddle
 mov cx, dx  ;максимальная длина
NBCalcMiddle:
 add cx, 4  ;+ 2 пробела и 2 черточки
 mov ax, XSize ;посреди экрана
 sub ax, cx
 shr ax, 1
 mov MB_x1, ax
 add ax, cx
 dec ax
 mov MB_x2, ax
 mov ax, YSize
 sub ax, 4
 shr ax, 1
 mov MB_y1, ax
 add ax, 3
 mov MB_y2, ax
 
 lea di, wSave ;сохраняем старый экран
 mov cx, XSize
 inc cx
 mov ax, MB_y1
 mul cx
 shl ax, 1
 mov si, ax
 shl cx, 2
 push ds
 push es
 push ds
 push es
 pop ds
 pop es
 rep movsw
 pop es
 pop ds
 
 push word ptr XScreen;сохраняем курсор
 
 mov ax, MB_x1 ;курсор на конец имени файла
 add ax, lenStr
 add ax, lenName
 inc al
 mov XScreen, al
 mov ax, MB_y2
 sub al, 2
 mov YScreen, al ;во второй строке
 
;нарисуем окно с рамкой
 call PrWin, MB_x1, MB_y1, MB_x2, MB_y2, SINGLE, MessageColor
 
 mov si, offName ;адрес имени
 mov bx, lenName ;длина имени, одновременно индекс конца введенной строки
 
NBPrName:   ;цикл ввода строки имени файла
 push si bx  ;сохраним используемые регистры
;выводим текст вместе с вводимым именем
 mov ax, MB_x1
 inc ax
 inc ax
 mov cx, MB_y1
 inc cx
 mov dx, MB_x2
 sub dx, ax
 lea di, sTextBuffer
 call PrText, ax, cx, dx, 2, di
 
 call SetCursor ;установка курсора
 pop bx si
 
NBKeyLoop:   ;цикл ожидания нажатия на клавишу
 mov ah, 0
 int 16h
 cmp ah, 1
 je NBEscape ;Escape - выходим без сохранения
 cmp al, 0dh
 je NBEnter  ;Enter - сохраняем имя
 cmp al, 8
 je NBBackSpace ;BackSpace - удаляем последний символ
 cmp al, \' \'
 jbe NBKeyLoop ;управляющие игнорируем
 cmp bx, 12
 jae NBKeyLoop ;максимум 12 символов
 mov [bx+si], al ;сохраняем
 inc bx  ;инкремент
 mov byte ptr[bx+si], 0 ;закрываем нулем
 inc XScreen  ;инкремент позиции на экране
 jmp NBPrName ;заново отрисовываем
 
NBBackSpace:   ;BackSpace
 test bx, bx 
 jz NBKeyLoop ;в начале - игнорируем
 dec bx  ;уменьшаем индекс
 mov byte ptr[bx+si], 0 ;признак конца
 dec XScreen  ;декремент позиции на экране
 jmp NBPrName ;заново отрисовываем
NBEscape:   ;Escape - выходим без сохранения
 mov di, 1  ;чтобы в бите D0 была единица
 jmp NBReturn
NBEnter:
 mov di, sOldName ;копируем имя по указанному адресу
 mov cx, bx  ;длина
 inc cx  ;+ 0
 push es
 push ds
 pop es
 rep movsb
 pop es
 xor di, di  ;D0 = 0
NBReturn:
 push di  ;сохраним признак
 lea si, wSave ;восстановим экран
 mov cx, XSize
 inc cx
 mov ax, MB_y1
 mul cx
 shl ax, 1
 mov di, ax
 shl cx, 2
 rep movsw
 pop di
 
 pop word ptr XScreen ;востановим позицию курсора
 call SetCursor
 
 shr di, 1  ;бит D0 в бит С - признак, как вышли!
 ret
NameBox endp
 
;вывод текста
;PT_x1, PT_y1 - координаты начала вывода
;PT_xcount - мах число символов по Х
;PT_ycount - число инфо строк
;PT_str - адрес строки, заканчивающейся 0, для перехода на другую строку 0dh,0ah
PrText proc  uses di, PT_x1:word, PT_y1:word, PT_xcount:word, PT_ycount:word, PT_str:word
;вычисляем смещение в сегменте видеоданных
 mov ax, ss:XSize
 inc ax
 mul PT_y1
 add ax, PT_x1
 shl ax, 1
 mov di, ax
 
 mov si, PT_str ;адрес строки
 mov dx, di  ;начало строки на экране, для подсчета адреса следующей строки
 mov cx, PT_xcount ;число колонок
 mov bx, PT_ycount ;число строк
PTRLoop:
 test bx, bx  ;кончилось?
 jz to_PrRet
PTCLoop:
 jcxz PrNextRow ;дошли до конца строки - переход на следующую строку
 lodsb
 cmp al, 0  ;дошли до конца строки?
 jnz PTCmp0d  ;нет, на проверку 0dh
 jcxz to_PrRet ;заполним до конца пробелами
 mov al, \' \'
PTEndRow_loop:
 stosb
 inc di
 loop PTEndRow_loop
;также заполним пробелами всю следующую строку
 cmp PT_ycount, 23 ;но только для всего экрана, для сообщений - игнорируем
 jbe PrRet
 cmp si, 2  ;для пустого файла - игнорируем
 jb PrRet
 cmp byte ptr [si-2], 0ah ;если последний символ 0ah - игнорируем, 
 je PrRet  ; для него уже очищено до конца!
 mov di, dx  ;адрес следующей строки
 add di, ss:XSize
 add di, ss:XSize
 inc di
 inc di
 mov dx, di
 dec bx
 mov cx, PT_xcount ;"опробелим"
PTEndRow_loop_2:
 stosb
 inc di
 loop PTEndRow_loop_2
to_PrRet:
 jmp PrRet
PTCmp0d:   ;анализируем дальше
 cmp al, 0dh
 jz PTCLoop  ;0dh игнорируем
 cmp al, 0ah
 jz PrNextRow ;по 0ah переходим на новую строку
 cmp al, 9
 jne PTstosb  ;обычный символ проосто выводим
 mov ax, di  ;табуляцию расширяем до позиции, кратной 8
 sub ax, dx
 shr ax, 1
 and ax, 7
 sub ax, 7
 neg ax
 mov ah, al  ;ah - число дополнительных пробелов
 mov al, \' \'
PTExpandTabLoop:
 jcxz PrNextRow ;дошли ли до края строки на экране
 cmp ah, 0
 je PTstosb  ;на вывод еще одного пробела
 stosb
 inc di
 dec cx  ;счетчик символов, которые еще можно вывести
 dec ah  ;счетчик дополнительных пробелов для расширения табуляции
 jnz PTExpandTabLoop
PTstosb:
 stosb   ;вывод символа
 inc di  ;обойдем атрибут
 dec cx  ;декремент счетчика
 jmp PTCLoop  ;на следующий
PrNextRow:   ;переход на следующую строку
 jcxz PrNextRow_1 ;сначала дополним до конца пробелами
 mov al, \' \'
PrEndRow_loop:
 stosb
 inc di
 loop PrEndRow_loop
PrNextRow_1:
 mov di, dx  ;адрес следующей строки
 add di, ss:XSize
 add di, ss:XSize
 inc di
 inc di
 mov dx, di
 dec bx  ;счетчик строк
 mov cx, PT_xcount ;заново счетчик колонок
;PTSearchLineEndLoop:
; cmp al, 0ah
; je PTRLoop
; lodsb
; cmp al, 0
; je PrRet
; jmp PTSearchLineEndLoop
 jmp PTRLoop  ;на повтор
PrRet:
 ret   ;все выведено!
PrText endp
 
;вывод в последней строке "F1 - помощь"
PrHelpMess proc
 mov ax, YSize
 inc ax
 mov di, XSize
 inc di
 mul di
 sub ax, sMessHelpLen ;длина строки
 shl ax, 1
 mov di, ax  ;адрес, куда выводим
 lea si, sMessHelp ;строка
PrHelp_loop:
 lodsb
 cmp al, 0
 je PrHelRet
 stosb
 inc di
 loop PrHelp_loop
PrHelRet:
 ret
PrHelpMess endp
 
;выход
exit proc
 cmp fChange, 0 ;было ли изменение?
 je EContinue
;1 строку сообщения
 call MessageBox, offset sChanged, 1
;возвращается скан-код нажатой клавиши
 cmp ah, 15h  ;Y?
 je EContinue ;Y - выходим
 jmp NewCursor ;восстановим курсор и продолжаем работать
EContinue:
 lea si, SaveScr ;восстановим эвесь экран
 xor di, di
 mov ax, XSize
 mov cx, YSize
 inc ax
 inc cx
 mul cx
 inc ax
 mov cx, ax
 rep movsw
 
 mov ah, 2  ;восстановим курсор
 mov bh, 0
 mov dx, PosOld
 int 10h
 mov ax, 4c00h ;выход в ДОС
 int 21h
exit endp
 
;индексы в массиве псевдографики
LU equ 0
RU equ 1
RD equ 2
LD equ 3
HH equ 4
VV equ 5
 
;индексы в массиве адресов псевдографики
SINGLE equ 0
DOUBLE equ 1
 
;сегмент данных
 .data
;краткая помощь по F1
sHelp  db \'F1 - эта помощь\', 0dh, 0ah
  db \'F2 - запись файла\', 0dh, 0ah
  db \'F3 - чтение файла\', 0dh, 0ah
  db 1ah,\'  - курсор вправо\', 0dh, 0ah
  db 1bh,\'  - курсор влево\', 0dh, 0ah
  db 18h,\'  - курсор вверх\', 0dh, 0ah
  db 19h,\'  - курсор вниз\', 0dh, 0ah
  db \'BSp- удалить символ слева\', 0dh, 0ah
  db \'Tab- вставить табуляцию\', 0dh, 0ah
  db \'Ent- перейти на новую строку\', 0dh, 0ah
  db \'Esc- выход\', 0
;подсказка о помощи в последней строке
sMessHelp db \' F1-помощь \',0
;длина подсказки
sMessHelpLen equ $-sMessHelp
;сообщение, добавляемое в сообщения об ошибках
sAnyKey  db 0dh,0ah,\'Нажмите на любую клавишу\',0
;сообщения об ошибках
sOpenError db \'Файл % не найден\',0
sReadError db \'Ошибка чтения файла %\',0
sSizeError db \'Длина файла % >= 65535\',0
sCreateError db \'Ошибка создания файла %\',0
sWriteError db \'Ошибка записи файла %\',0
;для запроса имени файла
sFileName db \'Имя файла: \',0
sReadFile db \'Чтение файла\', 0dh, 0ah, 0
sWriteFile db \'Запись файла\', 0dh, 0ah, 0
;для подтверждения продолжения при изменении файла
sChanged db \'Файл изменен, продолжать? (Y,N)\',0
;таблицы псевдографики
Borders  dw BorderSingle, BorderDouble
BorderSingle db 0dah,0bfh,0d9h,0c0h,0c4h,0b3h
BorderDouble db 0c9h,0bbh,0bch,0c8h,0cdh,0bah
;имя файла по-умолчанию
Default  db \'Noname.txt\',0
;цвета (атрибуты) окон в виде: ст байт - текст внутри, мл байт - рамка
;цвет основного окна
MainColor dw 1f17h
;цвет сообщения об ошибке
ErrorColor dw 4f47h
;цвет сообщения, например, ввода имени файла
MessageColor dw 3f37h
;таблица отрабатываемых кодов (скан-кодов)
KeyTable db 01h,48h,4bh,4dh,50h,3bh,3dh,3ch,0eh,0fh,1ch
;длина KeyTable
KeyTablelen equ $-KeyTable
;соответствующая таблица подпрограмм отработки
PrgTable dw Exit,KeyUp,KeyLeft,KeyRight
  dw KeyDown,KeyHelp,KeyRead,KeyWrite
  dw KeyBack,KeyInsert,KeyEnter
 
 .data?
Xsize dw ? ;размер экрана в колонках-1, т.е. индекс последней колонки на экране
Ysize dw ? ;размер экрана в строках-1, т.е. индекс последней строки на экране
FileSeg dw ? ;сегмент данных файла
FileLen dw ? ;длина данных файла
UpLine dw ? ;смещение в сегменте данных файла первой строки отображения на экране
CurLine dw ? ;смещение в сегменте данных файла текущей строки
PosOld dw ? ;сохраненная позиция курсора
XScreen db ? ;текущая позиция по Х на экране
YScreen db ? ;текущая позиция по Y на экране
XFile db ? ;текущая позиция по Х в текущей строке в файле
YFile db ? ;текущая позиция по Y в текущей строке в файле
fChange db ? ;флаг изменеия содержимого файла
FName db 128 dup (?) ;буфер для имени файла
SaveScr label word ;буфер для сохранения содержимого экрана текущей страницы
 
 end
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.05.2012, 14:52
Ответы с готовыми решениями:

Преобразование числового кода
Подскажите пожалуйста как можно программно реализовать алгоритм преобразование...

Преобразование слов со знаком из дополн. кода в прямой код.
Сессия, а разобраться уже не успеваю, помогите... Написать программу для...

Проверка кода с контролем по четности на правильность и преобразование в двоичную систему счисления
Проверка кода с контролем по четности на правильность и преобразование в...

Преобразование строки в её аналог на основе ASCII-кодов и поиск max и min кода
Привет, вот вроде как рабочий код , В начале проверка паролем, потом ввод...

fasm
org 100h mov cl,0 mov ch,255 cikl: mov ah,0eh shl ch,1 jc perivod mov...

6
Charles Kludge
Клюг
7645 / 3160 / 382
Регистрация: 03.05.2011
Сообщений: 8,382
15.05.2012, 16:43 2
собрал из-под тасма. Ничего интересного. Тупая перестановка имени макроса и его декларации - работа, конечно, творческая, но для ног. А дописывать асм-форматтер влом.
0
programmisto
92 / 137 / 0
Регистрация: 15.04.2012
Сообщений: 1,032
15.05.2012, 16:45 3
AIRWALK, всегда, когда надо в другой язык перегнать компилируешь код, который был, а затем исправляешь ошибки. Ну скомпилируй под фасмом этот код. Что он тебе выдает?
0
Искандар
Заблокирован
15.05.2012, 16:46 4
Цитата Сообщение от AIRWALK Посмотреть сообщение
1513
мне это даже читать влом, а ТС просит под фасм переделать
0
Charles Kludge
Клюг
7645 / 3160 / 382
Регистрация: 03.05.2011
Сообщений: 8,382
15.05.2012, 16:55 5
Цитата Сообщение от programmisto
Ну скомпилируй
Ты его сначала на тасме оттранслируй.
А компелируют на зоновески. Ты у нас в каждом байте затычкаКС.
0
Искандар
Заблокирован
15.05.2012, 16:56 6
Ты у нас в каждом байте затычка, в каждом бите единичка
0
programmisto
92 / 137 / 0
Регистрация: 15.04.2012
Сообщений: 1,032
15.05.2012, 17:14 7
Charles Kludge, просто раньше на Delphi писал. Там только компилировать можно было. Да и короче и понятнее сказать компилировать, чем оттранслировать.
0
15.05.2012, 17:14
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.05.2012, 17:14

Из Fasm в MASM
Ребят обращаюсь вот по какому вопросу , я сделал курсовой проект в FASM , с...

WinApi и fasm
Есть ли толковая документации по использованию winapi в fasm'e ?

SetSysColors (FASM)
Напишите пожалуйста программу (за меня), чтобы цвет всех окон Windows изменить....


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru