Как определить диск?
push cs
pop ds
......
disk:
db 0
db 0
db 0
dir:
dq 0
dq 0
......
dq 0
......
mov ax,4700h
xor dx,dx ;текущий диск!
mov si,offset dir ;сюда запишем полный путь без имени
int 21h ;диска и последнего символа '/'!
У меня есть вариант:
Вызывать эту функцию в цикле и инкрементировать dx до тех пор пока не исчезнет ошибка, а также сравнивать с первой итерацией. Так можно обнаружить диск, а затем дописать в начало имя в зависимости от полученного dx. Например, так:
mov di,offset disk
mov ax,0040h
add ax,dx
mov byte ptr ds:[di],al
mov ax,'\:'
mov byte ptr ds:[di+2],ax
А можно ли всё это сделать как-нибудь проще???
Насколько я понял, тебя интересует, как это можно сделать в DOS. Смутно припоминаю, что полное имя исполняемого файла программы DOS помещает после персональной для программы копии Environment-блока.
Поясню ещё разок:
Ведь в 47h функции DOS при dx = 0 (текущий диск) определяется путь к текущей директории, т.е. путь к "себе", а при dx = 1, 2, 3... выбирается диск A, B, C... При dx = 0 и dx = n результаты должны совпасть! Так и определится текущий диск.
Теперь вопрос:
Есть ли способ проще? Скажем вызываю функцию DOS XXh и получаю номер или букву диска на котором "я" сижу?
RE:
Насколько я понял, тебя интересует, как это можно сделать в DOS.
Всё правильно - в DOS'е! Но ведь приложения DOS'а могут выполняться и Windows'е в консольном режиме!
RE:
Смутно припоминаю, что полное имя исполняемого файла программы DOS помещает после персональной для программы копии Environment-блока.
А тут я не понял. Что это за персональная копия Environment-блока? Это не PSP случайно ли?
Я не знаю что куда там DOS помещает, я полный путь к "себе" хочу получить с помощью функции DOS 47h!
.stack 100h
.code
start:
push cs
pop ds
push ds
pop es
jmp above_dta
psevdo: db 0,0,0
my_dta:
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
disk:
db "e:\" ;На это можно не обращать внимания.
dir: ;Всёравно он переопределяется потом.
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
hehe:
dq 0
above_dta:
mov ax,1A00h
mov dx,offset my_dta
int 21h
mov ax,4700h
xor dx,dx
mov si,offset dir
int 21h
mov di,offset dir
xor dx,dx
mov ax,word ptr ds:[di]
cmp ax,dx
jne nextyy
call find_around
nextyy:
mov cx,0008h
inc dx
inc dx
define:
mov ax,4700h
inc dx
mov si,offset my_dta
int 21h
mov si,offset my_dta
mov di,offset dir
push cx
mov di,offset my_dta
xor dx,dx
mov ax,word ptr ds:[di]
cmp ax,dx
jne nextyyy
call find_around
nextyyy:
mov cx,0080h
repe cmpsb
pop cx
je enddefine
loop define
enddefine:
add dx,0060h
mov di,offset disk
mov byte ptr ds:[di],dl
;Всё работает, но если файл попадёт "чисто" на диск,
;скажем d:\me.exe,
;то он не поймёт на каком он диске!
jmp check
;А эта функция пытается сравнить окружающие файлы
;и если они одни
;и теже, то значит файл на этом диске.
find_around proc near
mov ax,1A00h
mov dx,offset local_dta
int 21h
jmp qwerty
qwe: db "*.*"
buf0: db 0
local_dta:
dq 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
buf11:
dq 0,0,0,0,0,0,0,0
buf22:
dq 0,0,0,0,0,0,0,0
qwerty:
mov di,offset buf0
mov al,byte ptr ds:[di]
cmp al,0
jne go_nexty
mov al,01h
mov byte ptr ds:[di],al
go_nexty:
xor cx,cx
go_nexty2:
mov ax,4E00h
mov dx,offset qwe
int 21h
jc qwe_end
jmp short gakar
qwe_next:
mov ax,4F00h
int 21h
jc qwe_end
gakar:
mov cx,0008h
mov si,???????????????????
jmp short qwe_next
buff0: db 0
qwe_end:
mov di,offset buff0
mov al,byte ptr ds:[di]
cmp al,0
jne go_nextyyy
mov cx,00010000b
jmp go_nexty2
go_nextyyy:
xor ax,ax
mov byte ptr ds:[di],al
mov ax,1A00h
mov dx,offset my_dta
int 21h
retn
find_around endp
check:
;jmp eeee
jmp short ttt
u: db "88.txt",0
ttt:
mov ax,3C00h
mov dx,offset u
xor cx,cx
int 21h
mov bx,ax
mov ax,4000h
mov dx,offset my_dta
mov cx,offset above_dta-offset my_dta
;mov dx,offset my_memory
;mov cx,offset endy-offset my_memory
int 21h
mov ax,3E00h
int 21h
eeee:
mov ax,0600h
mov dx,0007h
int 21h
mov ax,4C00h
int 21h
Можно ли как-нибудь без создавания дирректорий обойтись?
P.S.
На "худой конец" просто присваивается диск C, но это ерунда просто...
Недостаток в том, что если директория уже создана, то ничего не получается и присваивается диск C. И ещё: не получатся сменить директорию с помощью функции DOS 3Bh, чтобы текущая директория стала на другом диске!
.model small
.stack 100h
.code
start:
push cs
pop ds
push ds
pop es
jmp above_dta
psevdo: db 0,0,0
my_dta:
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
disk:
db 0,0,0 ;"e:\"
dir:
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
hehe:
dq 0
above_dta:
mov ax,1A00h
mov dx,offset my_dta
int 21h
mov ax,4700h
xor dx,dx
mov si,offset dir
int 21h
mov di,offset dir
xor dx,dx
mov ax,word ptr ds:[di]
cmp ax,dx
je eve
jmp jiu
way: db "\beyong40",0
eve:
mov ax,3900h
mov dx,offset way
int 21h
jnc jui
mov di,offset disk
mov ax,":c"
mov word ptr ds:[di],ax
jmp outy
jui:
mov ax,3B00h
mov dx,offset way
int 21h
mov ax,4700h
xor dx,dx
mov si,offset dir
int 21h
jiu:
inc dx
inc dx
mov cx,0008h
define:
mov ax,4700h
inc dx
mov si,offset my_dta
int 21h
mov si,offset my_dta
mov di,offset dir
push cx
mov cx,0080h
repe cmpsb
pop cx
je enddefine
loop define
enddefine:
add dx,0060h
mov di,offset disk
mov byte ptr ds:[di],dl
mov ax,'\:'
mov word ptr ds:[di+1],ax
outy:
xor dx,dx
call looloo
jmp check
looloo proc near
mov di,offset hehe-1
mov cx,offset hehe-offset dir
loo:
mov al,byte ptr ds:[di]
cmp al,dl
jne endloo
dec di
loop loo
endloo:
inc di
mov si,di
mov ax,'*\'
mov word ptr ds:[di],ax
mov ax,'e.'
mov word ptr ds:[di+2],ax
mov ax,'ex'
mov word ptr ds:[di+4],ax
retn
looloo endp
.....
.....
.....
check:
;jmp eeee
jmp short ttt
u: db "88.txt",0
ttt:
mov ax,3C00h
mov dx,offset u
xor cx,cx
int 21h
mov bx,ax
mov ax,4000h
mov dx,offset my_dta
mov cx,offset above_dta-offset my_dta
int 21h
mov ax,3E00h
int 21h
eeee:
mov ax,0600h
mov dx,0007h
int 21h
mov ax,4C00h
int 21h
Тот способ, о котором я тебе поведал, вообще не требует вызова каких-либо функций, если ты конечно в самом начале программы не изменяешь значения регистров ds и es. Я под DOS уже лет десять ничего не писал, поэтому мне нужно просмотреть свои архивы. Завтра напишу точно, как это делается.
В общем так... Перед запуском программы DOS помещает в регистры ds и es сегментный адрес PSP этой программы. В PSP по смещению 2Ch хранится сегментный адрес копии Environment-блока (там хранятся asciiz-строки с переменными среды). Ты в этом сегменте сначала должен найти слово с нулевым значением, затем убедиться, что после этого слова находится слово с единичным значением, и если это так, то сразу после этого слова должна быть asciiz-строка с полным именем исполняемого файла программы, которое как раз и начинается с имени диска (можешь выполнить дополнительную проверку: второй и третий символы этой строки всегда должны быть ":\"). Этот способ работает, начиная с DOS версии 3.0!
Читал я про PSP краткое описание, но на это слово по адресу 2Ch как-то совсем не обращал внимания!!! В Delphi есть функция ExtractFileDrive, ну я и подумал, что нечто аналогичное обязано быть и в Assembler'е!!! Спасибо ещё разок Phantom-84 за ценную подсказку!!!
Вот что у меня получилось:
.model small
.stack 100h
.code
start:
push cs
pop ds
mov di,002Ch
mov ax,word ptr es:[di]
push ax
pop es
xor di,di
mov cx,0FFFFh
xor ax,ax
inc ax
cld
repne scasb
inc di
mov si,di
dec ax
repnz scasb
mov cx,di
mov ax,si
sub cx,ax
mov di,offset buf
push es
pop ds
push cs
pop es
push cx
rep movsb
pop cx
push cs
pop ds
jmp end_buf
buf:
dq 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
dq 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
end_buf:
check:
jmp short ttt
u: db "88.txt",0
ttt:
mov ax,3C00h
mov dx,offset u
push cx
xor cx,cx
int 21h
mov bx,ax
mov ax,4000h
mov dx,offset buf
pop cx
int 21h
mov ax,3E00h
int 21h
mov ax,0600h
mov dx,0007h
int 21h
mov ax,4C00h
int 21h
end start
А в файле 88.txt выводится только то, что надо в формате ASCIZ!!!
чуваг, выучи неициализированыࡗе переменные, или юзай DUP
Что-то я о таком даже и не слышал...
DUP - это массив! Но от этого просто програмка короче быдет в блокноте, а размер от этого не меняется!
А всё-таки что такое неициализированные переменные???
[QUOTE=Meatcoins]А всё-таки что такое неициализированные переменные???[/QUOTE]Ты правда не знаешь, что такое неинициализированные переменные? Это во-первых, когда ты динамически распределяешь память с помощью соответствующих системных вызовов или просто в стеке, а во вторых, применительно к DOS например, когда ты размещаешь сегменты, в которых все переменные описаны без задания первоначального значения (типа "var db ?" или "buf rb 512"), в конце. Для обычного сегмента данных это тоже будет работать, если неинициализированные переменные разместить в конце. Основное преимущество неинициализированных переменных при их правильном размещении - это то что они не занимают места в исполняемых файлах. Короче структура DOS-программы должна быть такой: сначала все сегменты кода, затем сегмент данных, в конце которого находятся неинициализированные переменные, а уж после все heap-сегменты, включая стек. Кстати, в 32-разрядных ОС это тоже работает применительно к секциям.
Тогда вопрос:
1 - Что это за dgroup такой?
mov ax,dgroup
mov ds,ax
А можно так написать:
mov ax,seg data_buf
mov ds,ax
.....
.....
.data
....
....
data_buf: db ....
2 - А что если сегмент .data у меня будет составлять больше 64кбайт неинициализированных переменных и я с ним буду, скажем, побайтно работать, ну, например, так:
mov ax,word ptr ds:[di]
То есть мне надо будет нечто вроде проверки делать равно уже di == 0FFFFh или не равно?
Ну типа так:
add di,1
jc inc_ds
....
mov ax,word ptr ds:[di]
....
mov word ptr ds:[di],ax
....
inc_ds:
mov ax,ds
inc ax
mov ds,ax
....
mov ax,word ptr ds:[di]
....
mov word ptr ds:[di],ax
....
...
mov ax, [di]
...
mov [di], ax
add di, 2
jc inc_ds ; или даже "jz inc_ds"
...