связка Visual C++ 2017 с MASM

Тема в разделе "WASM.BEGINNERS", создана пользователем kol1978, 18 фев 2025 в 07:20.

  1. aa_dav

    aa_dav Active Member

    Публикаций:
    0
    Регистрация:
    24 дек 2008
    Сообщения:
    510
    Если взять этот исходник и скомпилировать с ключом -S получится не работающий пример если строка будет больше 2Гб.
    Если теперь взять этот исходник и скомпилировать с ключами -S -mcmodel=large, то получится работающий пример даже если строка будет больше 2Гб.
    Пользуйтесь.
     
  2. kol1978

    kol1978 Member

    Публикаций:
    0
    Регистрация:
    16 фев 2025
    Сообщения:
    32
    ну и еще раз! мною взято получено скомпилировано...но бинарник не получается(многократно говорил)! если вы так уверенны - покажите ваш работающий пример бинарника с - "даже если строка будет больше 2Гб."?
    --- Сообщение объединено, 22 фев 2025 в 06:03 ---
    из предыдущего моего утверждения код:
    Код (C):
    1. #include <unistd.h>
    2. char message[] = " \345\215\220 \320\245\320\260\320\271\320\273\321\214 \320\241\320\270 \345\215\220";
    3. int main(int argc, char *argv[])
    4. {
    5.   write(1, message, sizeof(message));
    6.   unsigned long syscall_nr = 60;
    7.   long exit_status = 0;
    8.  
    9.   syscall(syscall_nr, exit_status);
    10. }
    Код (ASM):
    1. .text
    2.         .globl  main
    3. main:
    4.         subq    $8, %rsp
    5.         movl    $25, %edx
    6.         movl    $1, %edi
    7.         movabsq $message, %rsi
    8.         movabsq $write, %rax
    9.         call    *%rax
    10.         xorl    %esi, %esi
    11.         movl    $60, %edi
    12.         xorl    %eax, %eax
    13.         movabsq $syscall, %rdx
    14.         call    *%rdx
    15.         xorl    %eax, %eax
    16.         addq    $8, %rsp
    17.         ret
    18. . = main + 2147483648
    19.         .globl  message
    20. .data
    21. message:
    22.         .string " \345\215\220 \320\245\320\260\320\271\320\273\321\214 \320\241\320\270 \345\215\220"
    23.  
    бинарник получается только с числом 1147483648, но с числом 2147483648 - не получается:
    Код (Text):
    1.  
    2. gcc -O3 -std=c++23 -no-pie -mcmodel=large hail_.S -o hail_
    3.  
    4. kol@kol:~/ASM/code16$ gcc -O3 -std=c++23 -mcmodel=large hail_.S -o hail_
    5. /usr/bin/ld: /tmp/ccbtvuP0.o: warning: relocation in read-only section `.text'
    6. /usr/bin/ld: warning: creating DT_TEXTREL in a PIE
    --- Сообщение объединено, 22 фев 2025 в 06:08 ---
    Хорошая идея проверки ключа -mcmodel=large : два кода на Си gcc и на ассемблере as - со строкой (или просто переменной) в секции data отстоящей от main на не менее 2гига. Жду примеры- ?
     
    Последнее редактирование: 22 фев 2025 в 06:09
  3. aa_dav

    aa_dav Active Member

    Публикаций:
    0
    Регистрация:
    24 дек 2008
    Сообщения:
    510
    Да, не получается, пасует линкер (ld) потому что ему ставят невыполнимую задачу.
    А ты сделай как я выше написал - получи .S файлы. Они генерируются еще до фазы линкера и компилятор их сгенерирует. Но первый при попытке из него создать бинарник будет падать с той же ошибкой на фазе линкера.
    Вот и смотри в эти исходники, сравнивай, осознавай за счёт чего первый не компилируется в бинарник, а второй да.
     
  4. kol1978

    kol1978 Member

    Публикаций:
    0
    Регистрация:
    16 фев 2025
    Сообщения:
    32
    если пример преодолеет ограничение 2 гига то :
    - какое ограничение для 64 битной системы? как проверить?
    --- Сообщение объединено, 22 фев 2025 в 06:28 ---
    привел две команды компаляции
    в обоих случаях бинарник получается (только в одном сообщение предупреждения...), но только в том случае если число менее 2 гигов. В очередной раз сообщай что ф. hail_.S получен ключом -S -mcmodel=large :
    Код (Text):
    1. gcc -O0 -S -mcmodel=large hail_.S -o hail_.S
    пример кода уже приводил.
    вы даже элементарного не делаете...и но без сомнений копипастами из инета - типа все у вас правильно... и еще раз: почему 2 гига е не 4 гига? и сколько для 64 битной должно быть - почему столько?
     
  5. MaKsIm

    MaKsIm Active Member

    Публикаций:
    0
    Регистрация:
    11 фев 2008
    Сообщения:
    144
    Код (C++):
    1. int main(int argc, char *argv[]) {
    2.   return 0;
    3. }
    Код (C++):
    1. int x;
    2. int getNextValue() {
    3.   return x + 1;
    4. }
    Код (Text):
    1. $ gcc -o ./test_val ./test_val_main.cpp ./test_val.cpp -O3 -std=c++23
    Снимок экрана_20250222_074918.png
    Код (Text):
    1. $ gcc -o ./test_val ./test_val_main.cpp ./test_val.cpp -O3 -std=c++23 -mcmodel=large
    Снимок экрана_20250222_074722.png
    Это выдает gcc под Linux
    Код (Text):
    1. $ gcc --version
    2. gcc (Gentoo 14.2.1_p20241221 p7) 14.2.1 20241221
    3. Copyright (C) 2024 Free Software Foundation, Inc.
    4. Это свободно распространяемое программное обеспечение. Условия копирования
    5. приведены в исходных текстах.
    6.  
    7.  Без гарантии каких-либо качеств, включая
    8. коммерческую ценность и применимость для каких-либо целей.
    9.  
     
  6. aa_dav

    aa_dav Active Member

    Публикаций:
    0
    Регистрация:
    24 дек 2008
    Сообщения:
    510
    Хм, действительно оказывается сами форматы выполнимых файлов хоть ELF на линуксе, хоть PE на Windows не поддерживают сегменты данных больше 2Гб.
    Это ограничения формата исполняемых файлов которое не обойти напрямую никак, поэтому пример тут не построишь.
    Если только наплодить кучу собственных сегментов по гигу? Хм. Но это мне уже лень заморачиваться...
    --- Сообщение объединено, 22 фев 2025 в 07:13 ---
    На винде (MinGW) вообще смешно получается - если массив глобальный сделать ровно 2млрд байт, то шланг экзешник собирает, но винда при попытке запуска выдаёт "это не исполнимый файл Windows", т.е. прям ломается формат экзешника, что винда уже не считает валидным. Забавно, забавно.
    --- Сообщение объединено, 22 фев 2025 в 07:15 ---
    Мда, незадача. Остаётся только поверить нам на слово.
    Но мы тут все честные джентльмены, ни слова неправды не прозвучало.
    --- Сообщение объединено, 22 фев 2025 в 07:37 ---
    Вообще, конечно, удивительно - 64-битную ось придумали, а исполнимый формат 64-битный полноценный не придумали. Парадокс. По сути получается, что у форматов ELF/PE те же проблемы - какие то смещения и размеры заданы 32-битными полями и 64-битности не подлежат.
    Мде, это даже для меня стало открытием.
     
  7. MaKsIm

    MaKsIm Active Member

    Публикаций:
    0
    Регистрация:
    11 фев 2008
    Сообщения:
    144
    Не 4 Гб потому что в 32 бита числа со знаком не помещаются в таком диапазоне. А со знаком они потому, что это смещения, а не абсолютные значения и знак там необходим.
     
  8. kol1978

    kol1978 Member

    Публикаций:
    0
    Регистрация:
    16 фев 2025
    Сообщения:
    32
    Вот и я говорю - парадокс...
    проверил ещё раз:
    Код (Text):
    1. gcc -O0 -fno-asynchronous-unwind-tables -fno-dwarf2-cfi-asm -Wall -S -mcmodel=large hail_.c -o hail_.S
    2. cat hail_.S
    3.  
    4. gcc -O3 -std=c++23 -fpie -mcmodel=large hail_.S -o hail_
    5. gcc -O3 -std=c++23 -no-pie -mcmodel=large hail_.S -o hail_
    6.  
    7. https://godbolt.org/
    8. -mcmodel=large -fpie
    9. -mcmodel=large -no-pie
    nano ./hail_.S :
    Код (ASM):
    1. .text
    2.     .globl  message
    3.     .globl    main
    4.     .type    main, @function
    5. main:
    6.     endbr64
    7.     pushq    %rbp
    8.     movq    %rsp, %rbp
    9.     pushq    %r15
    10.     pushq    %rbx
    11.     subq    $32, %rsp
    12. .L3:
    13.     leaq    .L3(%rip), %rbx
    14.     movabsq    $_GLOBAL_OFFSET_TABLE_-.L3, %r11
    15.     addq    %r11, %rbx
    16.     movl    %edi, -36(%rbp)
    17.     movq    %rsi, -48(%rbp)
    18.     movl    $25, %edx
    19.     movabsq    $message@GOTOFF, %rax
    20.     leaq    (%rbx,%rax), %rax
    21.     movq    %rax, %rsi
    22.     movl    $1, %edi
    23.     movq    %rbx, %r15
    24.     movabsq    $write@PLTOFF, %rax
    25.     addq    %rbx, %rax
    26.     call    *%rax
    27.     movq    $60, -32(%rbp)
    28.     movq    $0, -24(%rbp)
    29.     movq    -32(%rbp), %rax
    30.     movq    -24(%rbp), %rdx
    31.     movq    %rdx, %rsi
    32.     movq    %rax, %rdi
    33.     movq    %rbx, %r15
    34.     movl    $0, %eax
    35.     movabsq    $syscall@PLTOFF, %rdx
    36.     addq    %rbx, %rdx
    37.     call    *%rdx
    38.     movl    $0, %eax
    39.     addq    $32, %rsp
    40.     popq    %rbx
    41.     popq    %r15
    42.     popq    %rbp
    43.     ret
    44. #. = main + 1147483648
    45. . = main + 2147483648
    46.     .data
    47.     .size    message, 25
    48. message:
    49.     .string    " \345\215\220 \320\245\320\260\320\271\320\273\321\214 \320\241\320\270 \345\215\220"
    50.  
    компиляция : gcc -fpie -mcmodel=large hail_.S -o hail_
    --- Сообщение объединено, 22 фев 2025 в 08:06 ---
    Скачал структуру форматы выполнимых файлов хоть ELF в переводе...(буду читать), а точно дело в EFL?
    --- Сообщение объединено, 22 фев 2025 в 08:21 ---
    не понятен смысл сообщения... нужен нормальный код с пояснениями...
    endbr64 — это ассемблерная инструкция, которая используется для обнаружения недопустимых переходов (обычная защитная интел инструкция - не более).
     
  9. aa_dav

    aa_dav Active Member

    Публикаций:
    0
    Регистрация:
    24 дек 2008
    Сообщения:
    510
    Ну так на стек оверфлоу не раз писали.
    Вообще, конечно, несмотря на то, что пример с переполнением построить оказалось нетривиально, всё равно можно разглядывать разные выхлопы с mcmodel и без и видеть что компиль генерирует разный код.
     
  10. MaKsIm

    MaKsIm Active Member

    Публикаций:
    0
    Регистрация:
    11 фев 2008
    Сообщения:
    144
    Код (C++):
    1. // тест файла test_val_main.cpp
    2. int main(int argc, char *argv[]) { // это просто стартовая функция. Она ничего не делает. Нам интереснее вторая
    3.   return 0; // Возвращаем 0 и выходим
    4. }
    Код (C++):
    1. // текст файла test_val.cpp
    2. int x; // Некоторая глобальная переменная, которая будет размещена в секции данных
    3. int getNextValue() { // Функция, которая работает с глобальной переменной
    4.   return x + 1; // Достаточно простой манипуляции, чтобы функция не превратилась в inline, а осталась вызываемой
    5.   // Просто возвращаем значение глобальной переменной x увеличенное на 1, казалось бы
    6. }
    Команда компиляции этого примера сразу в бинарник (если делать S то ничего особо не изменится; я просто воспользуюсь IDA)
    Код (Bash):
    1. $ gcc -o ./test_val ./test_val_main.cpp ./test_val.cpp -O3 -std=c++23
    Снимок экрана_20250222_100719.png
    На cs в инструкции не обращаем внимания т.к. это самодеятельность IDA - нам это не интересно.
    А теперь откомпилируем с флагом -mcmodel=large
    Код (Bash):
    1. $ gcc -o ./test_val ./test_val_main.cpp ./test_val.cpp -O3 -std=c++23 -mcmodel=large
    Снимок экрана_20250222_101504.png
    И вот теперь компилятор намеренно применяет 64-битную арифметику для вычисления адресов, чтобы обойти ограничение в 2 Гб, которое есть у конструкции modr/m
    --- Сообщение объединено, 22 фев 2025 в 09:25 ---
    У вас тут asm код. GCC его не будет оптимизировать и отсюда флаг -mcmodel=large ничего вам не покажет. Вот именно поэтому я пропускаю стадию генерации .s файла
    --- Сообщение объединено, 22 фев 2025 в 09:44 ---
    О чем я тут говорю
    Код (Bash):
    1. $ gcc -S ./test_val_test_main.s ./test_val_main.cpp -O3 -std=c++23
    Создаем .s файл без флага -mcmodel=large
    Код (Bash):
    1. $ cat ./test_val_main.s
    2.  .file  "test_val_main.cpp"
    3.  .text
    4.  .section  .text.startup,"ax",@progbits
    5.  .p2align 4
    6.  .globl  main
    7.  .type  main, @function
    8. main:
    9. .LFB0:
    10.  .cfi_startproc
    11.  endbr64
    12.  xorl  %eax, %eax
    13.  ret
    14.  .cfi_endproc
    15. .LFE0:
    16.  .size  main, .-main
    17.  .ident  "GCC: (Gentoo 14.2.1_p20241221 p7) 14.2.1 20241221"
    18.  .section  .note.GNU-stack,"",@progbits
    19.  .section  .note.gnu.property,"a"
    20.  .align 8
    21.  .long  1f - 0f
    22.  .long  4f - 1f
    23.  .long  5
    24. 0:
    25.  .string "GNU"
    26. 1:
    27.  .align 8
    28.  .long  0xc0000002
    29.  .long  3f - 2f
    30. 2:
    31.  .long  0x3
    32. 3:
    33.  .align 8
    34. 4:
    Получили вот такой результат
    Код (Bash):
    1. $ gcc -S ./test_val_test.s ./test_val.cpp -O3 -std=c++23
    И тут без флага -mcmodel=large
    Код (Bash):
    1. $ cat ./test_val.s
    2.  .file  "test_val.cpp"
    3.  .text
    4.  .p2align 4
    5.  .globl  _Z12getNextValuev
    6.  .type  _Z12getNextValuev, @function
    7. _Z12getNextValuev:
    8. .LFB0:
    9.  .cfi_startproc
    10.  endbr64
    11.  movl  value(%rip), %eax
    12.  addl  $1, %eax
    13.  ret
    14.  .cfi_endproc
    15. .LFE0:
    16.  .size  _Z12getNextValuev, .-_Z12getNextValuev
    17.  .globl  value
    18.  .bss
    19.  .align 4
    20.  .type  value, @object
    21.  .size  value, 4
    22. value:
    23.  .zero  4
    24.  .ident  "GCC: (Gentoo 14.2.1_p20241221 p7) 14.2.1 20241221"
    25.  .section  .note.GNU-stack,"",@progbits
    26.  .section  .note.gnu.property,"a"
    27.  .align 8
    28.  .long  1f - 0f
    29.  .long  4f - 1f
    30.  .long  5
    31. 0:
    32.  .string "GNU"
    33. 1:
    34.  .align 8
    35.  .long  0xc0000002
    36.  .long  3f - 2f
    37. 2:
    38.  .long  0x3
    39. 3:
    40.  .align 8
    41. 4:
    И такой
    Код (Text):
    1. $ gcc -o ./test_val ./test_val_main.s ./test_val.s -O3 -std=c++23 -mcmodel=large
    2.  
    А вот пытаюсь применить флаг -mcmodel=large к уже созданным .s файлам. По идее компилятор должен использовать 64-битнуя арифметику для доступа к переменным
    Снимок экрана_20250222_104329.png
    Но у нас ничего не изменилось. В бинарнике все как в .s файле - арифметика указателей все так же использует modr/m с ограничением в +/-2Гб.
     
    Последнее редактирование: 22 фев 2025 в 09:45
  11. kol1978

    kol1978 Member

    Публикаций:
    0
    Регистрация:
    16 фев 2025
    Сообщения:
    32
    "А вот пытаюсь применить флаг -mcmodel=large к уже созданным .s файлам." - применение флагов gcc к ассемблерному коду бесполезно...это известно - не вижу тут логической связи... ощущение что вы пытаетесь запутать ситуацию, а не прояснить...
    Применяется флаг к коду Си добавляется код:
    Код (ASM):
    1.     leaq    .L3(%rip), %rbx
    2.     movabsq    $_GLOBAL_OFFSET_TABLE_-.L3, %r11
    3.     addq    %r11, %rbx
    4.     movl    %edi, -36(%rbp)
    5.     movq    %rsi, -48(%rbp)
    6.     movl    $25, %edx
    ясное дело что это "для чего то нужно"..., но это не проясняет ситуацию - почему нельзя скомпилировать мой пример?
    --- Сообщение объединено, 22 фев 2025 в 11:53 ---
    Предлагаю пойти дальше: давайте отвяжемся от ОС(если дело в ELF )... по примеру кода загрузчика который мною приводился - жду предложений и примеров кода?
    --- Сообщение объединено, 22 фев 2025 в 12:04 ---
    Ну давай так - это звучит как : мне лень и ли не знаю как просто это сделать что бы не напрягаться и поэтому не собираюсь тебя учить по крайней мере бесплатно...предлагаю - лучше ничего не писать сюда. в противном случае меня это тоже напрягает - отвечать и разбираться во всем этом вываливаемом хламе...
     
    Последнее редактирование: 22 фев 2025 в 12:04
  12. MaKsIm

    MaKsIm Active Member

    Публикаций:
    0
    Регистрация:
    11 фев 2008
    Сообщения:
    144
    И что вы тогда вот тут вот делаете?
    Это я пытаюсь запутать? Повторить сказанное в цитате и сказать, что согласен...

    Такое впечатление, что кто-то тренирует нейросетку.
     
  13. kol1978

    kol1978 Member

    Публикаций:
    0
    Регистрация:
    16 фев 2025
    Сообщения:
    32
    Ну...видимо вы плохо знаете linux... на сайте - https://godbolt.org/ используя флаги : -mcmodel=large -fpie -mcmodel=large -no-pie, можно получить разные варианты ассемблерного кода (хотя и тут один из них лишний - существует вариант по умолчанию) . Но! используя флаг -S для получения ассемблера можно получить только один вариант, но если использовать флаги (-mcmodel=large -fpie -mcmodel=large -no-pie) и потом результат дизассемблировать то можно получить оба варианта...так что это :
    Код (Text):
    1. cc -O3 -std=c++23 -fpie -mcmodel=large hail_.S -o hail_ <<<--- вот это что такое
    2. gcc -O3 -std=c++23 -no-pie -mcmodel=large hail_.S -o hail_ <<<--- а это?
    для бинарников и последующему возврату из них к ассемблеру (гидрой gdb аидой - это не суть).
    Можете посмотреть сами как (влияет ли) флаги ( -fpie ; -no-pie) на команду : gcc -O0 -fno-asynchronous-unwind-tables -fno-dwarf2-cfi-asm -Wall -S -mcmodel=large hail_.c -o hail_.S
    Влияет? удивите меня - может это мои дистрибутивы так реагируют..
    Ваши примеры не по существу вопроса поста: код на Си подразумевает наличие переменной отвечающей принципу её расположения как в ассемблерном коде :
    Код (Text):
    1.  
    2. . = main + 2147483648
    3.     .data
    и как следствие наличие трёх кодов - на Си , ассемблера из Си и самостоятельного ассемблера. Поэтому в теме поста фигурирует термин - связка...
    ps и не надо цепляться к словам...выше есть про флаги и ассемблерный код там промолчали... но в любом случае это не суть , а суть что пример (ваш) не отражает тему поста.
     
    Последнее редактирование: 22 фев 2025 в 17:14
  14. aa_dav

    aa_dav Active Member

    Публикаций:
    0
    Регистрация:
    24 дек 2008
    Сообщения:
    510
    А ты можешь объяснить при чём тут в твоей этой тираде в начале затесался линукс?
    Какое отношение вообще линукс имеет к ключам компиляции GCC?
    Ты чего то реально выдаёшь какую то хрень как будто нейросеть типа "чёрный ящик" когда несвязанные утверждения в чёрном ящике как будто бы якобы сливаются, но почему и как - это загадка черного ящика.
     
    MaKsIm нравится это.
  15. kol1978

    kol1978 Member

    Публикаций:
    0
    Регистрация:
    16 фев 2025
    Сообщения:
    32
    Знаешь это взаимно... и + это ответ не на твои вопросы... слишком много вопросов на вопросы - так что запутать все же пытаешься...нейросеть там не нейросеть...наверное не выяснить.
    Линукс имеет ровно такое отношение к gcc как и библиотеки и флаги и все это имеет отношение к компиляции! Результат компиляции зависит от того в каком дистрибутиве linux выполняется компиляция(поэтому). И когда говориться о linux подразумевается и ядро и все остальное gnu хозяйство - ну и поэтому GCC используется в контексте с linux.... и потому что в контексте с другой ОС ото уже не совсем gcc так как может и не совсем gnu.
    "Какое отношение вообще линукс имеет к ключам компиляции GCC?" - просто вопрос ради вопроса ...просто засоряет тему и ничего не проясняет.
     
  16. aa_dav

    aa_dav Active Member

    Публикаций:
    0
    Регистрация:
    24 дек 2008
    Сообщения:
    510
    Неа.
    Ты вообще неправильно ответил.