LINUX.ORG.RU

Assembler

 


0

2

думаю,что Вы очень хорошо знакомы с ядром Линукс. поэтому Вам будет очень просто объяснить мне то, что я сам понять не могу.

section .data
var db 'hi LOR'
section .text
global _start
_start:
//в регистр eax я помещаю номер системного вызова. системный возов,, это обращение пользовательской программы к ядру.  потому что сама она не недалена такими полномочиями.

имеет системные вызовы как 1-закрытие файла, 3 -чтение , 5-открытие и тд
mov ebx, 1
в регистр ebx для этой программы я помещаю дискрептор файла.
каждый процесс имеет свой уникальный номер, который называется дискрептор. ребята это из головы. я могу нагородить тут. поэтому пожалуйста поправте и объясните. только правда не смейтесь. отнеситесь серьезно даже к такой глупости, если находите..

и так каждый процесс имеет свой уникальный номер, то есть дискрептор. в Линуксе все файл, поэтому зовется дискрептор файла.  в оболочке по умолчание открыты три файла : стандартный ввод(0) , вывод(1) и поток ошибок(2). 
так как я хочу вывести на экран hi LOR то буду использовать дискрептор 1
mov ebx, 1

mov ecx, var-из этого регистра будет прочитано то что лежало в var
mov edx, 10 -длинна слова в байтах. ну я с запасом взял
int 0x80 -прерывание
mov eax, 1 -закрытие...
int 0x80

прерывание это команда ядру исполнить то что было написанно до него. вернее выше его. 
но как это прочитать? 

то есть системный вызов обратится к ядру, для того чтобы оно взяло из регистра ecx то что там лежит, так как в регистре ebx у нас 1то есть это дискрептор на вывод. значит надо вывести то что лижет в ecx. если бы в ebx лежало 0 то системный вызов ,который хранится в eax, обратился к ядру для того чтобы произошла запись в edx, так как 0 это системный вызов ввода. но о чем говорят тогда 4 или 3 которые лежат в eax? если я говорю mov eax , 4 mov ebx 1 то это значит системный возов на запись и дискрептор на вывод. не логично. записать что? ведь в eax хранится в данном случае номер системного вызова 4 на запись. значит моя программа обращается к ядру чтобы оно сделало запись. а дискрептор файла говорит куда? то есть дискрептор говорит на вывод, а это экран. так?

Чёт не то с синтаксисом, да ещё 32 бита. Дёргать едро не тру, дёргай либц и не страдай хернёй. И нет, полнейшая чушь. Зачем оно тебе? Если чисто теоретический интерес, возьми досбокс с досом, там прикольней.

anonymous ()
Ответ на: комментарий от anonymous

32 бита,потому что ось 32 битная.

если я говорю mov eax , 4 mov ebx 1 то это значит системный возов на запись и дискрептор на вывод. не логично. записать что? ведь в eax хранится в данном случае номер системного вызова 4 на запись. значит моя программа обращается к ядру чтобы оно сделало запись. а дискрептор файла говорит куда? то есть дискрептор говорит на вывод, а это экран. так? или нет?

linuxpc ()
Ответ на: комментарий от anonymous

Синтаксис - православный Intel. А по поводу всего остального абсолютно согласен. Не, ну, понимаю, там драйвер какой-нить специфичный, где нужно устройству регистры переключать (хотя даже тут ассемблер не нужен). Пускай ТС лучше берет какой-нить микроконтроллер и хоть закодится на своём ассемблере.

Unicode4all ★★★★ ()
Ответ на: комментарий от Unicode4all

я ребята очень пожалел,что не знал Assembler когда пришел учиться. учитель плавал,я тоже не мог прочитать что что лежит в file.s а это бы дало много ответов на мои вопросы. просто если что-то непонятно при компиляции создай file.s и ты многое поймешь. ну если конечно же знаешь Аssembler. мне это нужно..

подскажите что там не так в моем понимании синтаксиса?

linuxpc ()

Мне очень трудно читать твой текст, но вроде бы я понял что ты мало что понял :-), поэтому наверное тебе следует изучить ассемблер в отрыве от ядра, и не под DOS. Попробуй напиши свою «ОС», если уж любишь практику.

vladimir_vist ()

Мне кажется, ты путаешь системные вызовы (3=read, 4=write) и файловые дескрипторы (0=stdin, 1=stdout).
Ты почему-то считаешь, что главное - содержимое регистра ebx (номер дескриптора). Типа если там 0, то ядро будет читать, а если 1, то писать. А это вообще не так. Операция (читать или писать) определяется номером системного вызова из eax (3=read, 4=write).
А ebx - это в какой дескриптор читать или писать, это уже твое личное дело.

mov eax, 1 -закрытие...
int 0x80

Не закрытие, а выход, завершение работы программы (1=sys_exit)

bigbit ★★★★★ ()
Последнее исправление: bigbit (всего исправлений: 1)
Ответ на: комментарий от bigbit

ну это было размышление . и Вы правы, я так то путаю писать и читать)))

я же в конце пришел к выводу, что если в eax лежит допустим 4-write -писать, а в ebx-1 -вывод, то это можно понять, как системный вызов обращается к ядру с просьбой записать то что лежит в edx, а куда записать, это уже определяется значением в регистре ebx, а там 1, а это значит вывод стандартный. а стандартный вывод, это вывод на экран. так?

linuxpc ()
Ответ на: комментарий от linuxpc

или допустим что в eax лежит 3 , а в ebx 0. тогда это можно понимать, как системный вызов обращается ядру с просьбой прочитать, а от куда прочитать это сказанно в ebx, а там 0, а нуль это у нас стандартный ввод. а стандартный ввод это у нас клавиатура. значит ядро будет читать с клавиатуры. так?

linuxpc ()

Научись структурировать свои мысли и нормально задавать вопросы. Чувствую что ты что-то хотел спросить, но вижу поток несвязанных букв, поэтому отвечаю наугад.

Во-первых, ты путаешь номера системных вызовов для 32 и 64 бит, они разные. Для 32 бит write это 4.

Далее, в регистрах ты передаёшь ядру номер системного вызова (через eax) и его аргументы (через последующие регистры по порядку). Здесь, write принимает 3 аргумента - номер дескриптора (через ebx), адрес данных (через ecx) и размер данных (через edx).

После того как ты записал всё это в регистры и вызвал int 0x80, управление передаётся ядру. Прежде всего оно смотрит в eax, на всё остальное ему наплевать. Потом управление передаётся на код конкретного системного вызова и он уже разбирает свои аргументы как ему надо.

Здесь будет записано edx байт начиная с адреса ecx в файловый дескриптор из ebx. В ebx 1, это стандартный поток вывода, по умолчанию связанный с терминалом. Там может быть любой дескриптор - файла, сокета, даже stdin, в любом случае будет предпринята попытка записать туда данные, ибо это определяется только системным вызовом. В ecx адрес твоей строки var. В edx у тебя длина строки «с запасом» что неверно, ибо там должно быть точное число байт. Если ты сказал 10, значит прочитается 6 байт строки и 4 байта лежащих в памяти после неё. Там могут быть нули, мусор, другие данные твоего процесса, и это будет выведено в терминал. Либо ты можешь выйти за пределы отведённой тебе памяти и программа упадёт.

Для первого сисколла ты не заполнил eax вообще. Для второго (предполагаю что имелся в виду exit) ты не заполнил первый аргумент (код завершения в ebx), так что будет использована 1 которую ты положил туда раньше.

slovazap ★★★★★ ()
Ответ на: комментарий от slovazap

ну Вы угадали , что я хотел спросить , вернее понять. это никому не удавалось на этом форуме. Спасибо Вам огромное.

вот только один вопрос, если я создал файл, и решил в него записать с клавиатуры... то для начала мне его надо открыть. значит я mov eax , 5. но как мне теперь узнать дискрептор этого файла? как я знаю какой номер ему дало ядро?

linuxpc ()

дискрептор

лижет

возов

Я рекомендую для начала

1) Выучить русский
2) Научиться формулировать свои мысли

Читать ЭТО - просто боль и страдания.

reprimand ★★★★★ ()

ННП в твоём насме, юзай лучше пацанский Gas:

.section .text
  .global _start
  _start:
    movl $4, %eax # sys_write (syscall 4) put on Accumulator register
    movl $1, %ebx # stdout (fd 1) put on Base register (argument for sys_write)
    movl $hilor, %ecx # put data (long, pointer) on Counter register (also argument)
    movl $length, %edx # put data length on Data register (also argument)
    int $0x80 # interrupt 0x80, goto kernel (run syscall)
    movl $1, %eax # sys_exit
    movl $0, %ebx # 0
    int $0x80
.section .data
  hilor:
    .ascii "hi LOR\n"
    length = . - hilor
WitcherGeralt ★★ ()
Ответ на: комментарий от vladimir_vist

что -то не понял..

>file.txt
section .data
filenam db "file.txt"
section .data
global _start
_start:
mov eax, 5 --открыл файл
mow ebx, filename -- это будет дескриптор файла? 
или он сохранится в eax? 
а потом 
mov ebx, eax
так? 

linuxpc ()
Ответ на: комментарий от anonymous
$ head /usr/include/x86_64-linux-gnu/asm/unistd_*.h 
==> /usr/include/x86_64-linux-gnu/asm/unistd_32.h <==
#ifndef _ASM_X86_UNISTD_32_H
#define _ASM_X86_UNISTD_32_H 1

#define __NR_restart_syscall 0
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6

==> /usr/include/x86_64-linux-gnu/asm/unistd_64.h <==
#ifndef _ASM_X86_UNISTD_64_H
#define _ASM_X86_UNISTD_64_H 1

#define __NR_read 0
#define __NR_write 1
#define __NR_open 2
#define __NR_close 3
#define __NR_stat 4
#define __NR_fstat 5
#define __NR_lstat 6

Это? А какого чёрта тогда код выше у меня работает?

$ as --version
GNU assembler (GNU Binutils for Ubuntu) 2.30
...
This assembler was configured for a target of `x86_64-linux-gnu'.
as -o hilor.o hilor.gas
ld -o hilor.bin hilor.o
$ file hilor.o
hilor.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
$ file h.bin
h.bin: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped

P.S. Никогда не писал на асме, только несколько раз заглядывал туториал по Gas.

WitcherGeralt ★★ ()

Ой, как у нормальных бомбануло-то, прямо заглядение.

ТС-у на заметку: причин недовольства твоей простынёй две: объективная и субъективная.

Объективная — твою простыню действительно сложно читать из-за отсутствия владения русским языком. Следи за орфографией, за строчными и прописными буквами, чётко определись, где у тебя код, а где текст. Если это не ошибка, а ты считаешь, что «на ЛОРе и так сойдёт», то это неуважение к собеседникам.

Субъективная — у многих людей есть стереотип, что если молодой паренёк лезет в ассемблер, который в 2019 году никому не нужен, значит, ему нехрена делать, и надо побыстрее отбить у него хотелку. Это — проблемы этих людей, не обращай внимание. Читай только тех, кто тебе полезные наводки даёт, таких, как ни странно, в теме не меньше половины.

По теме сам ничего не посоветую, ассемблером последний раз занимался 20 лет назад.

Удачи.

hobbit ★★★★★ ()
Последнее исправление: hobbit (всего исправлений: 2)

вот все жалуются, что тс непонятно пишет, хотя сами толком ничего объяснить не могут.

анон выше, вон, правильный ссылки на abi кинул.

системный вызов можно рассматривать как обычную сишную функцию, агрументы в которую передаются через регистры. имена функций и соответствующие им номера можно посмотреть в файлах /usr/include/asm/unistd_32.h и /usr/include/asm/unistd_64.h. справка по сисколам есть во втором разделе man’а: man 2 syscall, man 2 syscalls, man 2 read, man 2 write и т.д.

в man 2 syscall есть табличка с инфой о том, какой аргумент какому регистру соотвестствует. в частности, для i386 последовательность регистров для аргументов такая: ebx ecx edx esi edi ebp.

если мы хотим что-то куда-то записать, то смотрим в man 2 write и читаем всё очень внимательно. видим нашу функцию-системный вызов:

write(int fd, const void *buf, size_t count);

исходя из этого определения в регистры процессора мы должны положить такие значения: eax - номер функции write - 4, ebx - номер дескриптора открытого файла (fd), пусть будет файл stdout с дескриптором 1 (если положить в ebx 0, то система сообщит, что в такой файл, stdin, нельзя ничего записать, а мы ведь именно пишем. в ecx кладём указатель на строку (*buf) и в edx - количество байт, которые должно записать ядро из нашей строки в stdout (count), это количество не нужно брать с запасом, так как можно схватить сегфолт, меньше - можно.

важно читать маны внимательно, в некоторых случаях порядок аргументов или их содержание в сишном интерфейсе может отличаться. об этом пишут обычно ближе к концу.

anonymous ()
Ответ на: комментарий от vladimir_vist

можете показать путь дескриптора файла? куда и откуда он пошел. ну это на словах конечно же... ну допустим так: при открытии файла создается новый десктриптор. mov eax, 5. куда он сразу попадает? в какой регистр? я не понял из примера. извините

linuxpc ()
Ответ на: комментарий от anonymous

что бы положить номер дескриптора открытого файла в ebx, его надо знать. я и пытаюсь это понять, вот открыли файл, создался дескриптор, отличный от 0, 1, 2 так как они уже были созданы до того, как я открыл файл. значит дескриптор файла может быть или 3 или 4 или 5 или 6 или 7 и тд. как это узнать? где он будет изначально хранится?

linuxpc ()