Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Asm для начинающих > предел 64к?


Автор: котъ 4.12.2005, 13:23
как в общем виде решить такую вот задачу :

с микроконтроллера в комп поступают байты данных, но их количество
превышает 64к !!!!!!!!

В одном сегменте данных программы .com и . exe они не могут разместиться !!

Как же их разместить и куда ???

Решаема ли эта задача для реального режима с применением дополнительной памяти в пределах мегабайта ?

А если байтов больше чем 1мб ? -- только защищенный режим с применением расширенной памяти ?
В какие сегменты в этом случае писать получаемые байты ?

СПАСИБО !!!!!!

Автор: Akina 4.12.2005, 15:16
Цитата
Как же их разместить и куда ???

Используй нормализацию указателей:

Код

; DS:SI - нормализуемый указатель
push ax
push dx
mov ax,ds
mov dx,si
and si, 0fh
and dx,0fff0h
shr dx,4
add ax,dx
mov ds,ax
pop dx
pop ax

Цитата
А если байтов больше чем 1мб ? -- только защищенный режим с применением расширенной памяти ?

DOS-GW extender

Автор: Chingachguk 4.12.2005, 15:18
Ну вообще-то проще всего сохранять данные на диск ;)

С трудом представляю себе задачу когда нужно держать ВСЕ данные обязательно в памяти.

В общем случае действительно можно использовать обычную память до 1 Мегабайта или функции DPMI. Это (DPMI) несложно, и поддерживается всеми версиями windows, а в случае чистого доса устанавливается простой драйвер (досовский).

Автор: Janus 4.12.2005, 18:11
А если нужно работать под чистым досом без дополнительных дров?

Что если не использовать файлы? Нужно в память помещать много данных, непрерывно. Как это сделать?

Есть что-то вроде этого:
Код

format mz
use16
entry cseg:start

include 'macro.inc'

stack 100h

segment dseg
;данные

segment cseg
start:
  push ds
  push ax

  push dseg
  pop  es

;тут код

segment tbl
  idtable db 0ffffh dup (0)

segment ptxt
  bytecode dw 0ffffh dup (0ffffh)

Так вот, программа получается огромной - 2 дополнительных сегмента, каждый по 64 Кб. Как сделать, чтобы можно было написать так:
Код

segment tbl
  idtable db 0

segment ptxt
  bytecode dw 0ffffh

Но чтобы можно было спокойно использовать по 64 Кб каждого сегмента. Естественно, в начале работы нужно как-то заполнить сегменты значениями(см. код выше).

Автор: Akina 4.12.2005, 21:50
с приведенным выше кодом нормализации я спокойно под ДОСом работал с массивом 200-300 кб.
Вернее с двумя массивами - 2 устройства синхроно получали данные, их надо было синхронно обрабатывать, но вот передача могда идти несинхронно - вплоть до того что второй массив мог пойти вообще после первого... получать в память была не моя забота, но массивы были от 100 до 160 кб... и их надо было накапливать... я выделял 2 MCB по 160 кб каждый, а обрабатывались они с нормализацией, потому сегнментация не мешала.

Автор: Chingachguk 4.12.2005, 22:09
Ну по поводу "удобной работы без сегментофф" есть много всякого - в том числе "нереальный" режим процессора (по книге Зубкова С.В.):

Цитата
10.4.5. Нереальный режим
Как мы уже знаем, при изменении режима скрытые части сегментных регистров сохраняют содержимое своих дескрипторов и ими можно пользоваться. Мы осуществили эту возможность в нашем первом примере, когда значения, занесенные в сегментные регистры в реальном режиме, использовались в защищенном. Возникает вопрос — а если сделать наоборот? В защищенном режиме загрузить сегментные регистры дескрипторами 4-гигабайтных сегментов с базой 0 и перейти в реальный режим? Оказывается, что это прекрасно срабатывает, и мы попадем в особый режим, который был обнаружен одновременно разными программистами и называется нереальным режимом (unreal mode), большим реальным режимом (BRM) или реальным flat-режимом (RFM). Чтобы перейти в нереальный режим, надо загрузить в CS перед переходом в реальный режим дескриптор 16-битного сегмента кода с базой 0 и лимитом 4 Гб и в остальные сегментные регистры — точно такие же дескрипторы сегментов данных.

Теперь весь дальнейший код программы, написанный для реального режима, больше не ограничен рамками 64-килобайтных сегментов и способен работать с любыми массивами. Можно подумать, что первый же обработчик прерывания от таймера загрузит в CS нормальное значение и все станет как обычно, но нет. Оказывается, что при создании дескриптора в скрытой части сегментного регистра в реальном режиме процессор не трогает поле лимита, а только изменяет базу: что бы мы ни записали в сегментный регистр, сегмент будет иметь размер 4 Гб. Если попробовать вернуться в DOS — DOS будет по-прежнему работать. Можно запускать программы такого рода:

        .model    tiny
        .code
        org        100h
start:  xor        ax,ax
        mov        ds,ax            ; DS = 0
; вывести символ в видеопамять:
        mov        word ptr ds:[0B8000h],8403h
        ret
        end        start

и они тоже будут работать. Единственное, что отключает этот режим, — программы, переключающиеся в защищенный режим и обратно, устанавливающие границы сегментов в 64 Кб, например любые программы, использующие расширители DOS.

Нереальный режим — идеальный вариант для программ, которые хотят пользоваться 32-битной адресацией и свободно обращаться ко всем прерываниям BIOS и DOS (традиционный способ состоял бы в работе в защищенном режиме с переключением в V86 для вызова BIOS или DOS, как это делается в случае DPMI).

Для переключения в этот режим можно воспользоваться, например, такой процедурой:

; область данных:
GDT label byte
        db        8 dup(0)            ; нулевой дескриптор
; 16-битный 4 Гб сегмент:
        db        0FFh,0FFh,0,0,0,1001001b,11001111b,0
gdtr    dw        16                  ; размер GDI
gdt_base dd      ?                    ; линейный адрес GDT

; код программы
; определить линейный адрес GDT
        xor        еах,еах
        mov        ax,cs
        shl        eax,4
        add        ax,offset GDT
; загрузить GDT из одного дескриптора (не считая нулевого)
        mov        gdt_base,eax
        lgdt      fword ptr gdtr
; перейти в защищенный режим
        cli
        mov        eax,cr0
        or        al,1
        mov        cr0,eax
        jmp        start_PM            ; сбросить очередь предвыборки
                                      ; Intel рекомендует
start_PM:                              ; делать jmp после каждой смены режима
; загрузить все сегментные регистры дескриптором с лимитом 4 Гб
        mov        ax,8                ; 8 - селектор нашего дескриптора
        mov        ds,ax
        mov        es,ax
        mov        fs,ax
        mov        gs,ax              ; перейти в реальный режим
        mov        eax,cr0
        and        al,0FEh
        mov        cr0,eax
        jmp        exit_PM
exit_PM:
; записать что-нибудь в каждый сегментный регистр
        хог        ах,ах
        mov        ds,ax
        mov        es,ax
        mov        fs,ax
        mov        gs,ax
        sti
        mov        ax,cs
        mov        ds,ax
; и все - теперь процессор находится в реальном режиме
; с неограниченными сегментами



А вообще-то переключить проц в PM и работать с большими кусками памяти - совсем не сложно smile

Автор: котъ 5.12.2005, 12:12
Всем огромное спасибо !!!!
Только я пока имею разряд чайника , но попробую разобраться.

Объястите пожалуйста только вот что : а ваще сколько может быть всего сегентов данных по 64к в . exe программе для доса???? - в пределах дополнительной памяти ? а в пределах расширенной?

Как их определить - задать в программе??!!!!!!!!!!!!!!!!!!!!!
Если не трудно то лучше показать на коротком примере.

Или в этом качестве используется дополнительный сегмент es или сегменты?

Относительно диска , я понял так , что в процессе набора из МК в комп
можно набирать данные по 64к и скидывать последовательно в .dat
файлы на диск !?????
А затем уж их обрабатывать по отдельности .
А что если эти файлы потом слить в один .dat ? и обрабатывать как один общий? И обрабатывать его частями по 64к?





Автор: Janus 5.12.2005, 16:46
Цитата(Akina @ 4.12.2005, 21:50)
с приведенным выше кодом нормализации я спокойно под ДОСом работал с массивом 200-300 кб.

А можно в двух словах самую суть? Чего мы этим добились? Или ссылку на статью.

Автор: Chingachguk 5.12.2005, 18:37
Цитата
А что если эти файлы потом слить в один .dat ? и обрабатывать как один общий? И обрабатывать его частями по 64к?


Можно. У файла как правило нет ограничений на размер. Открой его и пиши в него сколько хочешь сессий с данными. Или на каждую сессию свой файл. Имхо, тебе не нужно много памяти.

Автор: Akina 5.12.2005, 23:15
Цитата(Janus @ 5.12.2005, 17:46)
А можно в двух словах самую суть? Чего мы этим добились? Или ссылку на статью.

Да собственно это просто реализация механизма модели памяти huge. На АСМе. Не более и не менее. Исключение заворота сегмента...
статьи, извини, нет. не писАл...

Автор: котъ 6.12.2005, 09:34
Уважаемый Chingachguk!
попробовал писать в .dat файлы по мере заполнения массива сегмента
данных. Все получается ! Действительно можно обрабатывать неограниченные объемы !

Только если тебе не очень трудно , ответь пожалуйста
на старые вопросы !!!! а именно :


Объясни пожалуйста только вот что : а ваще сколько может быть всего сегентов данных по 64к в . exe программе для доса???? - в пределах дополнительной памяти ? а в пределах расширенной?

Как их определить - задать в программе??!!!!!!!!!!!!!!!!!!!!!
Если не трудно то лучше показать на коротком примере.!!!!!!!!!!!!!!!!!!!

Или в этом качестве используется дополнительный сегмент es или сегменты?
Извини за возможно глупые вопросы , но в литературе о них " забывают"
писать.
СПАСИБО!

Автор: oleg1973 6.12.2005, 10:49
а не про ще ли сделать FLAT режим (ну это когда предел сегмента в 4 гб в реальном режиме) ?

p.s.
вот кстати на сайте FASM
Цитата
The simple game engine for DOS, which runs in the 32-bit unREAL mode. It shows also how to use VESA and Sound Blaster.

http://flatassembler.net/examples.php

Автор: Chingachguk 6.12.2005, 15:53
Цитата
а ваще сколько может быть всего сегентов данных по 64к в . exe программе для доса???? - в пределах дополнительной памяти ?


Сделай команду mem /d /p. Увидишь примерно сколько у тебя памяти может быть. Около 550 000 байт. Число сегментофф ~ 550 000 / 2^16.

Цитата
а в пределах расширенной?


Ну если под расширенной понимать то, что после видеопамяти и до (за)BIOS'а (ом) в самых старших адресах, то еще парочка, а если ты про память за 1-м мегом (которая доступна через DPMI), то не менее 16 мегабайт / на размер сегмента.

Цитата
Как их определить - задать в программе??!!!!!!!!!!!!!!!!!!!!!


Какой программе ? com/exe на асме ? Для com сразу выделяется вся память за программой до видеопамяти, можешь сразу отступить от своего начала 64 Килобайта и делать с ней что хочешь. Для EXE зависит от линковки, но можно просто определить несколько сегментов .DATA?,
тебе будут доступный они после загрузки.

Код

; Example of EXE-Program
.286
StackSize equ 128
DataSeg Segment Para 'data'
        MyMessage db 'Hello from EXE !!!',13,10,'$'
        ErrorMess db 'Error !',13,10,'$'
        MemInfo   db 'Free mem:0000h',13,10,'$'
        TabHex    db '0123456789abcdef'
DataSeg Ends
CodeSeg segment Para 'code'
        assume cs:CodeSeg,ds:DataSeg,ss:MyStack
My_Pr proc
Main:
        mov  ax,DataSeg
        mov  ds,ax
        mov  dx,offset MyMessage
        mov  ah,09h
        int  21h
        call far ptr Stop
        call far ptr Far_Pr
; Check for size of Memory
        mov  ax,DataSeg
        mov  ds,ax
;        mov  ax,seg MyStack
;        mov  es,ax
        call ShowMem            ; Show free mem size
        mov  ah,48h
        mov  bx,0100h
        int  21h                ; Try to allocate 1000h bytes
        jnc  @NoError
        call @Error             ; Error message
@NoError:
        ; Free memory
        mov  bx,(StackSize shr 4) + 1
        mov  ah,4ah
        int  21h                ; Set new program size
        jnc  @MemFree
        call @Error
        jmp  @GoDos
@MemFree:
        call ShowMem            ; Show free mem size
        ; Try again to allocate 1000h bytes
        mov  ah,48h
        mov  bx,0100h
        int  21h                ; Try to allocate 1000h bytes attempt 2
        jnc  @NoErrorFinal
        call @Error             ; Error message
@NoErrorFinal:
        call ShowMem            ; Show free mem size
@GoDos: mov  ax,4c00h
        int  21h
My_Pr endp
ShowMem proc near
        mov  ah,48h
        mov  bx,0ffffh
        int  21h                ; Try to allocate ffffh bytes
        ; Error !
        mov  ax,bx              ; Free mem size
        mov  di,offset MemInfo + 9
        call HexChar
        mov  dx,offset MemInfo
        call Message
        retn
ShowMem endp
@Error proc near
        mov  dx,offset ErrorMess
        call Message
        retn
@Error endp
Message proc near
        mov  ah,09h
    int  21h
    retn
Message endp
HexChar proc near
        pusha
        push es
        push ds
        pop  es
        mov  cx,4
        mov  bx,offset TabHex
        cld
@GetHex:rol  ax,4
        push ax
        and  al,0fh
        xlat
        stosb
        pop  ax
        loop @GetHex
        pop  es
        popa
        retn
HexChar endp
CodeSeg Ends
DataSec Segment Para 'data'
        SecMess   db 'Called from Sec Segment !!!',13,10,'$'
DataSec Ends
SecSeg  segment Para 'code'
        assume cs:SecSeg,ds:DataSec,ss:MyStack
Far_Pr  proc far
        push ds
        mov  ax,DataSec
        mov  ds,ax
        mov  dx,offset SecMess
        mov  ah,09h
        int  21h
        call far ptr Stop
        pop  ds
        ret
Far_Pr  endp
SecSeg Ends
ThrSeg  segment Para 'code'
        assume cs:ThrSeg,ds:ThrSeg,ss:MyStack
Stop    proc far
        pusha
        xor  ah,ah
        int  16h
        popa
        ret
Stop    endp
ThrSeg Ends
MyStack Segment Para stack 'stack'
        db StackSize dup(?)
MyStack Ends
    End  Main

Автор: котъ 8.12.2005, 13:36
спасибо Chingachguk !

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)