LINUX.ORG.RU

Ты уверен, что никто? :)

Может просто не сильно светят этим, а сами вовсю у конкурентов так «код» периодически «заимствуют».

CrX ★★★★★
()

БЯМ, которые высокоуровневое описание разворачивает в Язык Ассемблера давно существуют. Обычно их называют компиляторами.

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

Надо как раз наоборот. Из языка ассемблера без комментариев и адекватных имён для адресов памяти перевести в что-то более высокоуровневое.

CrX ★★★★★
()

Ассемблеры находятся дальше от принципа работы ЛЛМ, чем языки высокого уровня. Генерация будет ещё хуже работать, кмк.

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

Да, но они не на основе БЯМ. И качество такой декомпиляции соответствующее. Точно так же, как раньше были программные переводчики, вроде PROMT. До того, как там стали использоваться нейросетки, качество перевода было соответствующим. Вот ТС и предлагает тут поступить так же — сделать декомпилятор, который выдаёт результат, читаемый, понимаемый и исправляемый человеком на порядок лучше, чем то, что выдают старые декомпиляторы.

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

Ну я попросил несколько известных сделать они ниасилили.

ya-betmen ★★★★★
() автор топика
Ответ на: комментарий от Bfgeshka

Вообще нет разницы, оно с наборами токенов работает.

Это ж будет новая эра опенсурса. Закон об отмывании кода приняли? Приняли! Погнали опенсурсить.

ya-betmen ★★★★★
() автор топика
Ответ на: комментарий от sabacs

Нет. БЯМ не детерминированы, в отличие от.

Это в популярные БЯМ-чаты специально случайность подмешивают, чтобы ответ каждый раз разный получался, а в случае с тренировкой на исходники это как раз не нужно. Такая нейросетка на идентичный машинный код всегда будет выдавать идентичный декомпилированный вариант. Валидный или нет — это уже другой вопрос.

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

Так и есть. Пытаюсь юзать ЛЛМ для ассемблеров для 6502/65816, постоянно галлюцинирует, упирается в несуществующие фичи, отказывается принимать собственную неправоту ссылаясь на несуществующие правила. В режиме агента просто уходит в бесконечный цикл и не может решить простейшие проблемы, лавинообразно ломая код. .

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

БЯМ БЯМе рознь!
давай, Гюльчатай, раскрой личико - где, когда, с кем, при каких обстоятельствах…
в смысле что за агент, какая LLM…

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

Codex 5.2/5.3, оба ведут себя тем безобразней, чем примитивнее сам язык, но чем больше сопутствующих знаний нужно иметь. Давеча при редактуре статьи оно запуталось в алгоритме (хотя казалось бы, как, если там два регистра общего назначения и пара десятков инструкций) и запороло мне перевод, пришлось заново самостоятельно набирать всё с полной проверкой. Потому что в одном месте статьи шла речь про 4 аргумента макроса, он не выкупил (!) что в конце статьи другой пример с тремя и начал ломать код рандомно вставляя четвертый (т.е. грубо, было txa,pha,tya,pha,txa,pha, он добавил по всему коду ещё один tya,pha, чем разнёс стек в щепки.

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

Ещё проблема, на которой жёстко проявилось:

Код был примерно такой (значительно упрощён):

.macro OPS OP
    OP "name1"
    OP "name2"
    OP "name3"
.endmacro

; Задача - посчитать количество элементов в OPS и раскрутить цикл по такому количеству элементов.

Решение:

.macro COUNT name
    _counter .set _counter + 1
.endmacro

.macro LIST_INIT
    _counter .set 0
.endmacro

.macro LIST_LOOP
    .repeat _counter, i
        ; Тут делаем, что надо, для примера:
        .out .sprintf("Луп %d", i)
    .endrep
.endmacro

И вызываем:

   LIST_INIT
   OPS COUNT


...
   LIST_LOOP

И всё работает, в выхлопе при компиляции будет

Луп 0
Луп 1
Луп 2

Проблема была в том, что в тестовом коде работает, а в проде - нет. И так и сяк сам крутил - не понял причину. Сунул в Codex. Тот начал мне заливать, что .repeat не может работать с переменными, что нужно константное выражение. Показал ему тестовый пример, который работает. Нет, кланкер говорит «ИНОГДА компилятор такое ПРОПУСКАЕТ». Поехавший. Короче потратил вечер на то, чтобы ему доказать, что код валидный, подставлял разные варианты, компилил, нет, упёрся и всё. Запускал через VS в режиме агента, тот вообще развалил половину проекта, но ничего не сделал правильного за час (!) работы.

В чём была проблема:

  • В проде код вызывается внутри .proc, что создаёт уровень scope. Из-за чего все переменные, объявленные глобально не видны (потому что он ищет _counter на текущем уровне. Решение:

.macro COUNT name
    ::_counter .set _counter + 1
.endmacro

.macro LIST_INIT
    ::_counter .set 0
.endmacro

.macro LIST_LOOP
    .repeat ::_counter, i
        ; Тут делаем, что надо, для примера:
        .out .sprintf("Луп %d", i)
    .endrep
.endmacro
PPP328 ★★★★★
()
Ответ на: комментарий от Bfgeshka

Если честно, даже для меня, упёротого T9-на-стероидах ненавистника, такая фича в ghidra могла бы вполне заинтересовать.

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

Декомпилятор лучше чем бредогенератор. Даже если он не выдаёт всякие украшательства, по крайней мере можно быть уверенным что выдача - настоящая. А за бредогенератором всё равно каждую строчку придётся с всё тем же ручным дизассемблером перепроверять. Если ты, конечно, не какую-то хальтуру кое как хочешь сгенерить. Но халтура не нужна, а ещё распространители должны быть наказаны за общественно вредные деяния.

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

Пытаюсь юзать ЛЛМ для ассемблеров для 6502/65816

Фу, тебя тоже пора в гпт-фанаты записывать.

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

Так тебе и надо.

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

Декомпилятор лучше чем бредогенератор. Даже если он не выдаёт всякие украшательства, по крайней мере можно быть уверенным что выдача - настоящая. А за бредогенератором всё равно каждую строчку придётся с всё тем же ручным дизассемблером перепроверять.

Так зачем же вручную. Пусть оно софтово само генерирует, само компилирует и смотрит, чтобы результирующий машинный код был идентичен исходно данному. Я же говорю «на основе», а не «БЯМ вместо декомпилятора» — обвязка с проверкой необходима.

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

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

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

Чтобы код был идентичен, тебе придётся ещё угадать каким компилятором и с какими опциями они компилировали. А этого компилятора у тебя может и вообще не оказаться.

Кроме того, учитывай вот это, из-за чего организовать побайтовую идентичность ещё сложнее.

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

Чтобы код был идентичен, тебе придётся ещё угадать каким компилятором и с какими опциями они компилировали.

По идее, эта задача решаема и даже не так уж и сложно, потому что можно просто перебрать всё по какому-то небольшому известному фрагменту (если не вообще тупо анализом бинарника находить какие-то характерные последовательности).

Но в целом я так-то тоже довольно скептичен к этой идее. По крайней мере на данном этапе развития. Хреново LLM с кодом работают, как ни крути.

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

Так им же не надо писать на ассемблере. Надо скармливать код и выхлоп в разных копиляторах с разными опциями. Скорее всего плюс-минус одни и те же алгоритмы будут скомпилены в похожие структуры в бинаре.

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

Погнали опенсурсить.

Если нужен аналог, то можно банально по документации к проге и ее скриншотам попросить модель реализовать то же самое с нуля, а не корпеть над машкодом)

goingUp ★★★★★
()

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

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

Если декомпилировпный код назад в тот же самый ассемблер компилируется, то чем это не пруф качественной декомпиляции?

FishHook
()
Ответ на: комментарий от ya-betmen

Написал факториал:

extern int f(int x) {
    if (x <= 1) return 1;
    return f(x - 1) * x;
}

Закинул его в compiler explorer с -O2. Получил:

f:
        mov     eax, 1
        cmp     edi, 1
        jle     .L1
.L2:
        imul    eax, edi
        sub     edi, 1
        cmp     edi, 1
        jne     .L2
.L1:
        ret

Затем закинул это в Claude Opus 4.6 Extended:

Please explain what this function does and translate it to Rust

Получил:

This is a factorial function. It computes n! (i.e., 1 × 2 × … × n).
Here's how it works: eax (the return value) starts at 1. If the input edi (n) is already ≤ 1, it jumps straight to the return. Otherwise, it enters a loop that multiplies eax by edi, decrements edi, and repeats until edi reaches 1.
In Rust:

fn f(n: i32) -> i32 {
    let mut result = 1;
    let mut i = n;
    while i > 1 {
        result *= i;
        i -= 1;
    }
    result
}
Or more idiomatically:

fn f(n: i32) -> i32 {
    (2..=n).product()
}

Кидаю тот же запрос в ChatGPT 5.4 Thinking, получил:

This function computes a factorial-like product of its input in edi and returns the result in eax.

More precisely:

It starts with eax = 1

If edi <= 1, it returns 1

Otherwise it multiplies eax by edi, then decrements edi

It repeats until edi == 1

Then it returns eax

So for positive integers greater than 1:

f(1) = 1

f(2) = 2

f(3) = 6

f(4) = 24

And also:

f(0) = 1

f(-5) = 1

That means this is basically factorial for n > 1, with all values <= 1 mapped to 1.

Step-by-step walkthrough
f:
        mov     eax, 1

Set result to 1.

        cmp     edi, 1
        jle     .L1

If argument edi <= 1, jump to return.

.L2:
        imul    eax, edi

Multiply current result by edi.

        sub     edi, 1

Decrease edi by 1.

        cmp     edi, 1
        jne     .L2

Keep looping until edi == 1.

.L1:
        ret

Return result in eax.

Simple Rust translation
fn f(mut n: i32) -> i32 {
	let mut result = 1;

	if n <= 1 {
		return result;
	}

	while n != 1 {
		result *= n;
		n -= 1;
	}

	result
}
More idiomatic Rust
fn f(n: i32) -> i32 {
	if n <= 1 {
		return 1;
	}

	let mut result = 1;
	for i in (2..=n).rev() {
		result *= i;
	}
	result
}
If you want exact overflow behavior closer to assembly

Because imul eax, edi does 32-bit multiplication with truncation, a closer Rust version is:

fn f(mut n: i32) -> i32 {
	let mut result = 1i32;

	if n <= 1 {
		return result;
	}

	while n != 1 {
		result = result.wrapping_mul(n);
		n -= 1;
	}

	result
}

This is the safest match to the machine code semantics.

For example:

f(5) = 120

f(0) = 1

f(-3) = 1

If you want, I can also annotate this assembly line by line in terms of registers and calling convention.

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

Пока алгоритм достаточно понятен нейронке (влезает в контекст и т. п.), она его поймёт/напишет хоть на C, хоть на Rust, хоть на Python, хоть на Assembler. Когда алгоритм/общая структура нейронки становится слишком сложным, нейронка лажает. Надо декомпозировать задачу на части, которые может прожевать нейронка.

Из любопытства засунул тот же промт в DeepSeek - он тоже справился с задачей (понял, что это факториал и переписал на Rust). Но в целом надо понимать, что бесплатные версии нейронок тупее платных, так что на чём-то сложнее DeepSeek быстрее обломается (а на чём-то совсем сложном обломаются все).

KivApple ★★★★★
()
Последнее исправление: KivApple (всего исправлений: 2)
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)