Eugene
Нагугли реализации менеджера памяти. Возьми какой-нибудь простой и реализуй на асме. В каком-то отдельном сегменте (64кб тебе хватит?) Потом можно будет переделать под любой размер памяти. Я тебе даже больше скажу. 💯% есть уже готовые реализации на асме. Бери и используй.
Eugene
И зачем тебе связный список байтов - это бред, так никто строки не делает. У тебя 1 символ будет занимать несколько байт памяти.
Eugene
И скорость работы будет никакущая.
s54820
ну раз такая пляска, как мне в сишарп использовать ассемблер для доступа к msr регистру?
Без драйвера никак. А с драйвером абсолютно фиолетово, откуда DeviceIoControl() вызывать, хоть из JavaScript.
s54820
@MrMiscipitlick если ты собираешься часто менять строки (например, ты пишешь текстовый редактор), можно делать строки в виде связного списка кусков, чтобы избежать лишних реаллокаций и копирований. Но обычно это всё не нужно.
The Bird of Hermes
Нет, результат возвращается в регистрах (обычно al, ax, eax, st(0)).
Делать возврат в регистрах неудобно, и регистры засираются, и количество их не резиновое
Eugene
Делать возврат в регистрах неудобно, и регистры засираются, и количество их не резиновое
Делай как тебе удобно, но практика такова, чтот одно значение возвращантся в регистрах во всех соглашениях о вызовах. Остальное геморно. Если только передать функции указатель и по нему записывать в переменную, но это не всегда нужно и удобно.
Ask
жоловаться тут только не надо что тебе регистров не хватает в отличии от остального мира)
Eugene
Это скорее про вставку и удаление.
Надо ещё где-то указатели хранить. Причём, в обе стороны.
The Bird of Hermes
Делай как тебе удобно, но практика такова, чтот одно значение возвращантся в регистрах во всех соглашениях о вызовах. Остальное геморно. Если только передать функции указатель и по нему записывать в переменную, но это не всегда нужно и удобно.
Ну я лично делаю через директиву arg, при вызове сначала смещая стек на количество байт для выходных параметров, потом размещаю входные, а после вызова смещаю обратно на количество входных. Это даже легче, чем с регистрами - ну, по крайней мере пользоваться этим
The Bird of Hermes
На вершине стека остаются только выходные
The Bird of Hermes
И не приходится думать ни о том, что регистров не хватит, ни об экспорте переменных для выходных параметров. Или это тоже неэффективно?
s54820
Надо ещё где-то указатели хранить. Причём, в обе стороны.
Ну да. У тебя чанки, у чанка есть указатель, длина, флаги и массив с куском строки. Но я же сказал, это для всяких специальных случаев. Для обычных коротких строк никакого смысла нет заморачиваться. Тогда разве что хак с длиной по отрицательному смещению оправдывает себя, если длина нужна часто.
Eugene
Обычно нет смысла изобретать 🚴‍♂. Всё уже украдено изобретено до нас :)
The Bird of Hermes
Обычно нет смысла изобретать 🚴‍♂. Всё уже украдено изобретено до нас :)
Ну проблема в том, что в учебниках почему-то я не встречал таких приколюх, там не пишут ни про язык для процедур, ни про uses, ни про local, ни про arg
The Bird of Hermes
Возможно где-то есть директива, которая выделяет локальные переменные и автоматически кладёт их на вершину стека при завершении, однако мне такую найти не удалось
Eugene
Возможно где-то есть директива, которая выделяет локальные переменные и автоматически кладёт их на вершину стека при завершении, однако мне такую найти не удалось
Потому что так делать не принято. Во-первых, тебе может быть не нужен результат, придётся делать лишний pop. Во-вторых сохранять все регистры в процедуре нет смысла (лишний код, лишние такты). Можно сохранять bx, si, di (и bp, sp, естественно), аx, cx, dx использовать для передачи параметров и возврата результата. Ну и флаг CF.
Eugene
А если ты регистры эти не сохраняешь, почему бы не использовать их для возврата?
Eugene
Зачем pop, просто увеличу sp
Потому что pop — 1 байт, а add sp,N — 3 байта
The Bird of Hermes
Почему не будет-то? ret X
Ну потому что это указатель стека, если его менять, то он будет указывать не на то место, где лежит адрес возврата из процедуры.
The Bird of Hermes
Адрес возврата из процедуры лежит в стеке
The Bird of Hermes
Потому что pop — 1 байт, а add sp,N — 3 байта
Это 1 байт только если у меня 1 выходной параметр, а если их 2, 3, 5, 10 то выгоднее перемещать указатель стека
The Bird of Hermes
Потому что pop — 1 байт, а add sp,N — 3 байта
Да и pop вытащит куда-то это значение из стека, очищай его потом
Eugene
Я не понимаю о чём ты и что пытаешься сделать. Вызов процедуры делается обычно так: push Параметр push Параметр call Процедура Процедура: push bp mov bp,sp ... leave ret 4
The Bird of Hermes
asmproc proc cpp near uses eax arg point:word,num:dword,mun:dword ... ret asmproc endp
The Bird of Hermes
Я о вот такой штуке говорю
Eugene
Соглашение cpp оставляет в стеке параметры.
Eugene
pascal или stdcall можно использовать
The Bird of Hermes
Соглашение cpp оставляет в стеке параметры.
Мне и надо чтобы он сохранял в стеке параметры, но не все, а только выходные
The Bird of Hermes
Чтобы было по-человечески, отправил входные, получил выходные
Eugene
У тебя цель какая? Скорость кода, размер, минимизация использования регистров или что-то ещё?
The Bird of Hermes
У тебя цель какая? Скорость кода, размер, минимизация использования регистров или что-то ещё?
Хочу использовать стек для входа и выхода, чтобы убрались входные параметры и остались только выходные, и чтобы всё это делалось внутри процедуры
The Bird of Hermes
Остались на вершине стека после выхода из процедуры
The Bird of Hermes
Зачем? Цель?
Для минимизации использования регистров (ситуации разные бывают, и выход может мне перекрывать используемый регистр, это заставит его тоже в стек кидать, потом возвращать) и соответственно отсутствия ограничений в количестве выходных параметров
The Bird of Hermes
Что ты пытаешься городить, я читал и ничего не понял
Моя цель такова: кинул в стек входные параметры, процедура выполнилась, в стеке остались выходные. При этом чтобы все телодвижения по организации этого эффекта выполнялись в процедуре, а вызов выглядел как-то так: push входные_параметры call процедура pop выходные_параметры
Eugene
Я художник, я так вижу (с) :)
The Bird of Hermes
Я художник, я так вижу (с) :)
Ну это должно быть возможно. В теории. Передача в стеке и стирание переданных параметров из стека уже есть
The Bird of Hermes
Осталось сделать так, чтобы при закрытии на вершину ложились выходные
The Bird of Hermes
Как-то мне с трудом верится, что передачу параметров через стек предусмотрели, а возврат - нет
s54820
Ну это должно быть возможно. В теории. Передача в стеке и стирание переданных параметров из стека уже есть
Вроде в паскале так было. В стеке после вызова метода оставался this (или как там у них? self?) объекта (видимо в расчёте на то, что у этого же объекта будут вызваны ещё методы). Я так понял, что ты хочешь что-то вроде: push 1 push 2 push 3 call testproc ; esp+0 = baadf00d ; esp+4 = aabbccdd add esp,8 ret proc testproc x,y,z mov [z],0xaabbccdd mov [y],0xbaadf00d leave ret 4 ; Передали 12, вытолкнули 4 (x), 8 осталось (y и z). endp Нужно и для leave/ret 4 сделать нормальный макрос, и для вызова, и всё равно регистры будут удобнее и быстрее.
Eugene
Как-то мне с трудом верится, что передачу параметров через стек предусмотрели, а возврат - нет
Потому что результат, как правило, один или два, а параметров может быть много. Классика — возврат через регистр или по указателю, переданному через параметр.
The Bird of Hermes
Я никогда не писал на си)
Leon
Ну так я не против, но мне для нормальной реализации только и надо, что динамическое выделение памяти
Я как всегда отвечу на старые сообщения но тебе не обойтись без менеджера памяти. Общая идея такова - берёшь у ОС большими кусками по мере необходимости, по 100 КБ например и внутри организовываешь собственную кучу (heap) где и выделяешь память кусочками для строк и остального по мере необходимости.
disba1ancer
Нет
Очень просто, первым неявным аргументом передаётся указатель на область памяти куда надо положить результат, это при условии, что структура не влезла в регистры возврата
The Bird of Hermes
В ассемблере
disba1ancer
Предлагаешь сделать это явно?
Можешь попробовать, но в принципе ты можешь сделать любым способом, который в голову придёт
Aiwan \ (•◡•) / _bot
Остались на вершине стека после выхода из процедуры
sub esp, 2×4 out 1,2 push in push in call stdcall pop out 1 pop out 2
The Bird of Hermes
sub esp, 2×4 out 1,2 push in push in call stdcall pop out 1 pop out 2
Stdcall затирает все параметры, он и выходные затрет
The Bird of Hermes
По сути я так и делал, только с cpp и вручную затирал входные параметры
The Bird of Hermes
нет
А как ему указать, какие затирать, а какие нет
Aiwan \ (•◡•) / _bot
А как ему указать, какие затирать, а какие нет
реализацией. у тя в руках асм. делай что хочешь
Aiwan \ (•◡•) / _bot
это ты уже сам играйся со стеком, что, где по каким адресам у тя в стеке хранится, от этого и отталлкивайся для грамотного управления
The Bird of Hermes
На это можно как-то повлиять?
Aiwan \ (•◡•) / _bot
влияешь ты
The Bird of Hermes
не он, а ты
Я определяю только затрет он всё или не затрет ничего
Aiwan \ (•◡•) / _bot
The Bird of Hermes
да, или частично что то затрет.
А мне надо чтобы он затер, но не всё
Aiwan \ (•◡•) / _bot
только я вот предложил вариант где не надо ничего спецально затирать. в частности выходные параметры
The Bird of Hermes
только я вот предложил вариант где не надо ничего спецально затирать. в частности выходные параметры
А как мне отделить входные параметры от выходных, чтобы функция знала, ху из ху
Aiwan \ (•◡•) / _bot
если изобретаешь велосипед - изучи какработают стандартные, классические велосипеды
Aiwan \ (•◡•) / _bot
А как мне отделить входные параметры от выходных, чтобы функция знала, ху из ху
а как функция узнает параметры? приведи пример на чистом асме, без всяких директив, макросов, и меток. как в дизассемлере без отладочной инфы
The Bird of Hermes
До вызова функции