Какой Динамический язык.NET имеет больше смысла учиться, Iron Ruby или Iron Python?

TL: DR: используйте gcc -m32.

.code32 делает not изменение формата выходного файла, и именно это определяет режим, в котором будет работать ваша программа. вам не нужно запускать 32-битный код в режиме 64 бит. .code32 предназначен для сборки «чужого» машинного кода, который может потребоваться в качестве данных, или для экспорта в сегменте общей памяти. Если это не то, что вы делаете, избегайте его, чтобы получить ошибки времени сборки, когда вы создаете .S в неправильном режиме, если у него есть, например, команды push или pop.

Предложение: используйте расширение .S для рукописного ассемблера. (gcc foo.S будет запускать его через препроцессор C до as, поэтому вы можете #include заголовок с номерами системного вызова, например). Кроме того, он отличает его от выхода компилятора .s (от gcc foo.c -O3 -S).

Чтобы создать 32-битные двоичные файлы, используйте одну из этих команд

gcc -g foo.S -o foo -m32 -nostdlib -static  # static binary with absolutely no libraries or startup code
                       # -nostdlib by itself makes static executables on Linux, but not OS X.

gcc -g foo.S -o foo -m32                  # dynamic binary including the startup boilerplate code.  Use with code that defines a main() but not a _start

Документация для nostdlib, -nostartfiles и -static .


Использование функций libc из _start (см. конец этого ответа для примера)

Некоторые функции, такие как функции malloc(3) или stdio, включая printf(3), зависят от инициализации некоторых глобальных данных (например, FILE *stdout и объекта, на который он фактически указывает).

gcc -nostartfiles оставляет из кода шаблона CRT _start, но все же ссылки libc (динамически, по умолчанию). В Linux общие библиотеки могут иметь разделы инициализатора, которые запускаются динамическим компоновщиком, когда он загружает их, прежде чем переходить к вашей точке входа _start. Таким образом, gcc -nostartfiles hello.S все еще позволяет вам называть printf. Для динамического исполняемого файла ядро ​​запускает на нем /lib/ld-linux.so.2 вместо его непосредственного использования (используйте readelf -a, чтобы увидеть строку «ELF интерпретатор» в вашем двоичном файле). Когда ваш _start в конечном итоге будет запущен, не все регистры будут обнулены, потому что динамический компоновщик выполнил код в вашем процессе.

Однако gcc -nostartfiles -static hello.S свяжется, но сбой во время выполнения, если вы вызываете printf или что-то, не вызывая внутренние функции init glibc. (см. комментарий Майкла Пётча).


Конечно, вы можете поместить любую комбинацию файлов .c, .S и .o в одну и ту же командную строку, чтобы связать их все в один исполняемый файл , Если у вас есть C, не забудьте -Og -Wall -Wextra: вы не хотите отлаживать ваш asm, когда проблема была чем-то простым в C, который вызывает это, о котором мог бы предупредить компилятор.

Используйте -v, чтобы gcc показывал вам команды, которые он запускает для сборки и соединения. Для этого «вручную»:

as foo.S -o foo.o -g --32 &&      # skips the preprocessor
ld -o foo foo.o  -m elf_i386

file foo
foo: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped

gcc -nostdlib -m32 легче запомнить и ввести, чем два разных варианта для as и ld (--32 и -m elf_i386). Кроме того, он работает на всех платформах, включая те, где исполняемый формат не является ELF. (Но примеры Linux не будут работать в OS X, потому что номера системных вызовов различны или в Windows, потому что в нем даже не используется int 0x80 ABI.)


NASM / YASM

gcc не может обрабатывать синтаксис NASM. (-masm=intel больше похож на MASM, чем на синтаксис NASM, где вам нужно offset symbol, чтобы получить адрес как немедленный). И, конечно, директивы различны (например, .globl vs global).

Вы можете построить с помощью nasm или yasm , затем свяжите .o с gcc, как указано выше, или ld напрямую.

Я использую сценарий оболочки, чтобы избежать повторного ввода одного и того же имени файла с тремя разными расширениями. (nasm и yasm по умолчанию file.asm -> file.o, в отличие от вывода GNU as по умолчанию a.out). Используйте это с помощью -m32, чтобы собрать и связать 32-разрядные исполняемые файлы ELF. Не все ОС используют ELF, поэтому этот скрипт менее переносим, ​​чем использование gcc -nostdlib -m32 для ссылки будет ..

#!/bin/sh
# usage: asm-link [-q] [-m32] foo.asm  [assembler options ...]
# Just use a Makefile for anything non-trivial.  This script is intentionally minimal and doesn't handle multiple source files

verbose=1                       # defaults
fmt=-felf64
#ldopt=-melf_i386

while getopts 'm:vq' opt; do
    case "$opt" in
        m)  if [ "m$OPTARG" = "m32" ]; then
                fmt=-felf32
                ldopt=-melf_i386
            fi
            if [ "m$OPTARG" = "mx32" ]; then
                fmt=-felfx32
                ldopt=-melf32_x86_64
            fi
            # default is -m64
            ;;
        q)  verbose=0 ;;
        v)  verbose=1 ;;
    esac
done
shift "$((OPTIND-1))"   # Shift off the options and optional --

src=$1
base=${src%.*}
shift

[ "$verbose" = 1 ] && set -x    # print commands as they're run, like make

#yasm "$fmt" -Worphan-labels -gdwarf2 "$src" "$@" &&
nasm "$fmt" -Worphan-labels -g -Fdwarf "$src" "$@" &&
    ld $ldopt -o "$base" "$base.o"

# yasm -gdwarf2 includes even .local labels so they show up in objdump output
# nasm defaults to that behaviour of including even .local labels

# nasm defaults to STABS debugging format, but -g is not the default

Я предпочитаю yasm по нескольким причинам, в том числе по умолчанию для создания long- nop s вместо заполнения со многими однобайтными nop s. Это приводит к беспорядочному выводу разборки, а также к замедлению, если nops когда-либо выполняются. (В NASM вам необходимо использовать макрос smartalign.)


Пример: программа, использующая функции libc из _start

# hello32.S

#include    // syscall numbers.  only #defines, no C declarations left after CPP to cause asm syntax errors

.text
#.global main   # uncomment these to let this code work as _start, or as main called by glibc _start
#main:
#.weak _start

.global _start
_start:
        mov     $__NR_gettimeofday, %eax  # make a syscall that we can see in strace output so we know when we get here
        int     $0x80

        push    %esp
        push    $print_fmt
        call   printf

        #xor    %ebx,%ebx                 # _exit(0)
        #mov    $__NR_exit_group, %eax    # same as glibc's _exit(2) wrapper
        #int    $0x80                     # won't flush the stdio buffer

        movl    $0, (%esp)   # reuse the stack slots we set up for printf, instead of popping
        call    exit         # exit(3) does an fflush and other cleanup

        #add    $8, %esp     # pop the space reserved by the two pushes
        #ret                 # only works in main, not _start

.section .rodata
print_fmt: .asciz "Hello, World!\n%%esp at startup = %#lx\n"

$ gcc -m32 -nostdlib hello32.S
/tmp/ccHNGx24.o: In function `_start':
(.text+0x7): undefined reference to `printf'
...
$ gcc -m32 hello32.S
/tmp/ccQ4SOR8.o: In function `_start':
(.text+0x0): multiple definition of `_start'
...

Не работает во время выполнения, потому что ничего не вызывает функции glibc init. (__libc_init_first, __dl_tls_setup и __libc_csu_init в этом порядке, в соответствии с комментарием Майкла Пётча. Существуют и другие реализации libc, в том числе MUSL , который предназначен для статической компоновки и работает без вызовов инициализации .)

$ gcc -m32 -nostartfiles -static hello32.S     # fails at run-time
$ file a.out
a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, BuildID[sha1]=ef4b74b1c29618d89ad60dbc6f9517d7cdec3236, not stripped
$ strace -s128 ./a.out
execve("./a.out", ["./a.out"], [/* 70 vars */]) = 0
[ Process PID=29681 runs in 32 bit mode. ]
gettimeofday(NULL, NULL)                = 0
--- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=0} ---
+++ killed by SIGSEGV (core dumped) +++
Segmentation fault (core dumped)

Вы также можете gdb ./a.out и запустить b _start, layout reg, run и посмотреть, что произойдет.


$ gcc -m32 -nostartfiles hello32.S             # Correct command line
$ file a.out
a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=7b0a731f9b24a77bee41c13ec562ba2a459d91c7, not stripped

$ ./a.out
Hello, World!
%esp at startup = 0xffdf7460

$ ltrace -s128 ./a.out > /dev/null
printf("Hello, World!\n%%esp at startup = %#lx\n", 0xff937510)      = 43    # note the different address: Address-space layout randomization at work
exit(0 
+++ exited (status 0) +++

$ strace -s128 ./a.out > /dev/null        # redirect stdout so we don't see a mix of normal output and trace output
execve("./a.out", ["./a.out"], [/* 70 vars */]) = 0
[ Process PID=29729 runs in 32 bit mode. ]
brk(0)                                  = 0x834e000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
....   more syscalls from dynamic linker code
open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
mmap2(NULL, 1814236, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xfffffffff7556000    # map the executable text section of the library
... more stuff
# end of dynamic linker's code, finally jumps to our _start

gettimeofday({1461874556, 431117}, NULL) = 0
fstat64(1, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0  # stdio is figuring out whether stdout is a terminal or not
ioctl(1, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, 0xff938870) = -1 ENOTTY (Inappropriate ioctl for device)
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xfffffffff7743000      # 4k buffer for stdout
write(1, "Hello, World!\n%esp at startup = 0xff938fb0\n", 43) = 43
exit_group(0)                           = ?
+++ exited with 0 +++

Если бы мы использовали _exit(0) или сделали систему sys_exit называть себя int 0x80, , то write(2) не было бы . Если stdout перенаправлен на не-tty, по умолчанию он заполняется с полным буфером (не с буферизацией строки), поэтому write(2) запускается только fflush(3) как часть exit(3). Без перенаправления вызов printf(3) со строкой, содержащей символы новой строки, будет немедленно скрыт.

Поведение в зависимости от того, является ли stdout терминалом, может быть желательно, но только если вы делаете это специально, а не по ошибке.

5
задан burning_LEGION 11 August 2012 в 18:00
поделиться

6 ответов

Если это, 'Какой язык работает лучше на CLR', затем прямо сейчас, IronPython без труда побеждает.

В течение длительного срока, хотя, 'какой язык будет учить меня больше и служить мне лучше в моей карьере как программист', определенно сказал бы я IronRuby (это будет верно для CPython по сравнению с CRuby также),

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

Так или иначе это, вероятно, собирается убывать в войну пламени.Прошу прощения

4
ответ дан 18 December 2019 в 12:04
поделиться

Не входя в относительные достоинства языков (который был бы всем конкурсом pissing сам по себе), IronPython (стабильные 1.1.1, бета 2.0) далее приезжает в разработке, чем IronRuby (альфа)

5
ответ дан 18 December 2019 в 12:04
поделиться

Какой бы ни Вы выбираете, смотрите на IronEditor - это является большим для проигрывания вокруг. Я в настоящее время использую его, чтобы попытаться взять те языки сам...

3
ответ дан 18 December 2019 в 12:04
поделиться

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

IronRuby является большим, но остерегайтесь: для попытки его, необходимо разобраться в коде от SVN и скомпилировать его собой. Или можно загрузить Динамическую Silverlight SDK и получить его тот путь, но необходимо будет потратить когда-то, изучая эту среду также.

0
ответ дан 18 December 2019 в 12:04
поделиться

Я просто хочу упомянуть, что существует также версия ДОЛЛАРА JavaScript (JScript), который является моим персональным fav. Если бы Вы ищете новый язык для изучения для использования доллара, я предложил бы ironpython, как упомянуто, это дальше приезжает в долларе. Python также довольно популярен вне доллара для программирования gui и предлагает Django для mvc веб-приложений.

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

1
ответ дан 18 December 2019 в 12:04
поделиться

Я пошел бы для IronPython в данный момент, так как существует много книг/информации вокруг для него (IronPython В Действии просто становится законченным).

Я лично изучил бы IronRuby, потому что я предпочитаю способ, которым Ruby работает по Python и так как это - одно из того же, затем выбирают, какой язык Вы предпочитаете.

2
ответ дан 18 December 2019 в 12:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: