Montaj Dili Sorgulama


21

Mümkün olan en kısa montaj dili alıntısını yazın .

Bir print-quinetalimatı veya eşdeğeri yoksa, istediğiniz herhangi bir ISA'yı kullanın . Örnekler arasında x86, MIPS, SPARC, MMIX, IBM BAL, MIX, VAX, JVM, ARM vb.

_printfG / Ç için C standart kitaplığının işlevine (veya JVM bayt kodu için Java eşdeğerine) bağlayabilirsiniz .

Uzunluk, veri bölümünün hem talimat sayısı hem de boyutu açısından değerlendirilecektir. Çözümler en az iki talimat içermelidir.

Ayraç , monte edilen makine kodunu değil, montaj kodunu yazdırmalıdır .


3
Oh vay, bu zor bir ses gibi geliyor
anonim korkak

Yanıtlar:


20

x86 Linux, AT&T sözdizimi: 244

push $10
push $34
push $s
push $34
push $37
push $37
push $s
call printf
mov $0,%ebx
mov $1,%eax
int $128
s:.ascii "push $10
push $34
push $s
push $34
push $37
push $37
push $s
call printf
mov $0,%cebx
mov $1,%ceax
int $128
s:.ascii %c%s%c%c"

(Ben bu konuda o derlenmiş: gcc -nostartfiles -lc quine.S -o quine)


Bu iç karartıcı, şimdi :-(
Joey

1
Genellikle "iş için doğru araç" derdim, ama sonra tekrar, burada doğru gelmiyor: D
JB

Yine de benimkinden daha doğru gibi görünüyor ;-)
Joey

5

(Via JVM bytecode Montaj Jasmin ) - 952 960 990

.class public Q
.super java/io/File
.method public static main([Ljava/lang/String;)V
.limit stack 9
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc ".class public Q%n.super java/io/File%n.method public static main([Ljava/lang/String;)V%n.limit stack 9%ngetstatic java/lang/System/out Ljava/io/PrintStream;%nldc %c%s%c%nldc 3%nanewarray java/lang/Object%ndup%ndup%nldc 0%nldc 34%ninvokestatic java/lang/Integer/valueOf(I)Ljava/lang/Integer;%ndup_x2%naastore%nldc 2%nswap%naastore%ndup2%nswap%nldc 1%nswap%naastore%ninvokevirtual java/io/PrintStream/printf(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;%npop%nreturn%n.end method"
ldc 3
anewarray java/lang/Object
dup
dup
ldc 0
ldc 34
invokestatic java/lang/Integer/valueOf(I)Ljava/lang/Integer;
dup_x2
aastore
ldc 2
swap
aastore
dup2
swap
ldc 1
swap
aastore
invokevirtual java/io/PrintStream/printf(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
pop
return
.end method

Ne yazık ki Jasmin, Microsoft'un izin verdiği kadar güzel numaraya izin vermiyor ilasm. Ancak JVM'nin her türlü eğlenceli şeyi yapan altı farklı duptalimatı var. Yığında öğeleri yeniden düzenlemek, .NET'in desteklemediği bir şeydir.

Her halükarda, sanırım iki girişimden hiçbiri en kısa kod için ciddi yarışmacılar değil, sanırım onları daha kısa yapmak zor. Bu nedenle sadece tamlık için :-)

Yığında neler olduğu hakkında bilgi içeren yorumlu sürüm:

.class public Q
.super java/io/File
.method public static main([Ljava/lang/String;)V
.limit stack 9
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc ".class public Q%n.super java/io/File%n.method public static main([Ljava/lang/String;)V%n.limit stack 9%ngetstatic java/lang/System/out Ljava/io/PrintStream;%nldc %c%s%c%nldc 3%nanewarray java/lang/Object%ndup%ndup%nldc 0%nldc 34%ninvokestatic java/lang/Integer/valueOf(I)Ljava/lang/Integer;%ndup_x2%naastore%nldc 2%nswap%naastore%ndup2%nswap%nldc 1%nswap%naastore%ninvokevirtual java/io/PrintStream/printf(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;%npop%nreturn%n.end method"
ldc 3       ; stack; System.out, string, 3
anewarray java/lang/Object    ; stack: System.out, string, Object[3]
dup
dup    ; stack: System.out, string, array, array, array
ldc 0  ; stack: System.out, string, array, array, array, 0
ldc 34   ; stack: System.out, string, array, array, array, 0, 34
invokestatic java/lang/Integer/valueOf(I)Ljava/lang/Integer;
dup_x2   ; stack: System.out, string, array, array, 34, array, 0, 34
aastore  ; stack: System.out, string, array, array, 34
ldc 2    ; stack: System.out, string, array, array, 34, 2
swap     ; stack: System.out, string, array, array, 2, 34
aastore  ; stack: System.out, string, array
dup2     ; stack: System.out, string, array, string, array
swap     ; stack: System.out, string, array, array, string
ldc 1    ; stack: System.out, string, array, array, string, 1
swap     ; stack: System.out, string, array, array, 1, string
aastore  ; stack: System.out, string, array
invokevirtual java/io/PrintStream/printf(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
pop
return
.end method

Tarih:

  • 2011-02-07 02:09 (990) - İlk çalışan versiyon.
  • 2011-02-07 02:11 (960) - ya da ldcdaha kısadır .bipushiconst_*
  • 2011-02-07 02:30 (952) - Java.lang.Object'ten miras almam gerektiğini kim söylüyor? Diğer sınıf isimleri çok daha kısadır :-)

4

x86 Linux için gaz (89 bayt, yedi talimat)

Teknik olarak, bu hile yapıyor.

mov $4,%al
mov $1,%bl
mov $b,%ecx
mov $89,%dl
int $128
mov %bl,%al
int $128
b:.incbin"a"

Adlı bir dosyaya kaydedin ve adlı akomutları oluşturmak için aşağıdaki komutlarla birleştirin a.out.

as -o a.o ; ld a.o

Yönerge .incbin, geçerli konumda bir dosya kelimesi içerir. Kaynak kodun kendisini eklemek için bunu kullanırsanız, güzel bir soru alırsınız.


3

Windows .COM Biçimi: 307 karakter

A86 kullanarak 51 bayta birleştirir. DOS Int21 AH = 9 işlevi (stdout'a yazma dizesi) dışında hiçbir dış kitaplık gerektirmez.

db 185
db  51
db   0
db 190
db   0
db   1
db 191
db  47
db   1
db 172
db 178
db  10
db 199
db   6
db  45
db   1
db  32
db  32
db 180
db   0
db 246
db 242
db 128
db 196
db  48
db 136
db  37
db  79
db  10
db 192
db 117
db 242
db 180
db   9
db 186
db  42
db   1
db 205
db  33
db 226
db 221
db 195
db 100
db  98
db  32
db  32
db  51
db  49
db  10
db  13
db  36

Korkarım 357 bayt sayıyorum. (ve program aslında 408 çıktı) Yine de güzel bir uygulama. Db'd montaj kaynağını dahil etmek isteyebilirsiniz, böylece diğer izleyiciler doğrudan bir görünüm elde edebilir.
JB

@JB: CR \ NL içermiyordum. Şimdi bakarak, gerçekten tek bir db satırına veri koymak gerekirdi. Bu daha küçük olur.
Skizz

3

NASM, 223 bayt

%define a "%define "
%define b "db "
%define c "%deftok "
%define d "a, 97, 32, 34, a, 34, 10, a, 98, 32, 34, b, 34, 10, a, 99, 32, 34, c, 34, 10, a, 100, 32, 34, d, 34, 10, c, 101, 32, 100, 10, b, 101, 10"
%deftok e d
db e

Kabul edilen cevabı yenmek!


2

.NET CIL - 623 669 691 723 727

.assembly H{}.method void M(){.entrypoint.locals init(string)ldstr".assembly H{0}{1}.method void M(){0}.entrypoint.locals init(string)ldstr{2}{3}{2}stloc 0ldloc 0ldc.i4 4newarr object dup dup dup dup ldc.i4 0ldstr{2}{0}{2}stelem.ref ldc.i4 1ldstr{2}{1}{2}stelem.ref ldc.i4 2ldc.i4 34box char stelem.ref ldc.i4 3ldloc 0stelem.ref call void[mscorlib]System.Console::Write(string,object[])ret{1}"stloc 0ldloc 0ldc.i4 4newarr object dup dup dup dup ldc.i4 0ldstr"{"stelem.ref ldc.i4 1ldstr"}"stelem.ref ldc.i4 2ldc.i4 34box char stelem.ref ldc.i4 3ldloc 0stelem.ref call void[mscorlib]System.Console::Write(string,object[])ret}

Tek bir satır, sonunda satır sonu yok.

Biçimlendirilmiş ve yorumlanmış ilk sürüm (artık bir quine olmasa bile) - genel konseptten çok fazla sapmam olası değil:

.assembly H{}
.method void M() {
  .entrypoint
  .locals init (
    string,
    object[]
  )
  // the string
  ldstr".assembly H{0}{1}.method void M(){0}.entrypoint.locals init(string,object[])ldstr{2}{3}{2}stloc.0 ldloc.0 ldc.i4.4 newarr object stloc.1 ldloc.1 ldc.i4.0 ldstr{2}{0}{2} stelem.ref ldloc.1 ldc.i4.1 ldstr{2}{1}{2} stelem.ref ldloc.1 ldc.i4.2 ldc.i4 34 box char stelem.ref ldloc.1 ldc.i4.3 ldloc.0 stelem.ref ldloc.1 call void[mscorlib]System.Console::Write(string,object[])ret{1}"
  stloc.0   // store in first local var
  ldloc.0   // load again. Going to be the first argument to Console::Write
  ldc.i4.4 newarr object stloc.1   // create new array and store in local var
  ldloc.1 ldc.i4.0 ldstr"{" stelem.ref   // we need a literal brace
  ldloc.1 ldc.i4.1 ldstr"}" stelem.ref   // closing, too
  ldloc.1 ldc.i4.2 ldc.i4 34 box char stelem.ref   // double quote
  ldloc.1 ldc.i4.3 ldloc.0 stelem.ref   // our format string from before
  ldloc.1 // load array
  call void[mscorlib]System.Console::Write(string,object[]) // output
  ret
}

Tarihçe :

  • 2011-02-06 16:48 (727) - İlk çalışan versiyon.
  • 2011-02-06 17:14 (723) - Bir dizi dizgesinden sonra bir alana ihtiyacım yok.
  • 2011-02-06 17:21 (691) - her seferinde dupyazmaktan daha kısadır ldloc.1.
  • 2011-02-06 17:24 (669) - Herhangi bir değişmez alandan sonra boşluklara ihtiyacım yok ve son belirteci değişmez yapmak için ldloc.1yazılabilir ldloc 1. Ortaya çıkan bayt kodu büyük olasılıkla daha büyük, ancak montajcı kodu hakkında, bu yüzden daha az umursamadım :-)
  • 2011-02-06 17:34 (623) - object[]Yerel değişken olarak ihtiyacım yok ; Bunları doğrudan yığın üzerinde yapabilirim. Güzel.

[] Nesneyi biçimlendirilmemiş sürümden
kaldırdığınız anlaşılıyor

@Aurel: Aslında, belirtildiği gibi, biçimlendirilmiş ilk sürümdür. Fikir hala aynı, bu yüzden tekrar güncellemeyeceğim.
Joey

2

x86 Linux için gaz, 184176 bayt

.globl main
main:movw $34,B+87
push $B
call printf
call printf
pop B
ret
.data
B:.ascii".globl main
main:movw $34,B+87
push $B
call printf
call printf
pop B
ret
.data
B:.ascii"

İle oluşturun gcc -m32 -o a.out quine.S. ( -m32İşletim sisteminiz zaten 32 bit ise isteğe bağlıdır.)

Eklemek için düzenlendi:puts Bunun yerine çağrılacak izin kurallarını değiştirirsek 182 174 baytta printfyapılabilir :

.globl main
main:movw $34,B+86
push $B+1
call puts
call puts
pop B
ret
.data
B:.ascii"
.globl main
main:movw $34,B+86
push $B+1
call puts
call puts
pop B
ret
.data
B:.ascii"

(Bunun, öncekinden farklı olarak, sonlandırıcı bir satırsonu olduğunu unutmayın.)


Kısalığı takdir ediyorum. Ancak printf / puts'a ek olarak, aslında açık bir şekilde izin verilmeyen standart C prolog / epiloga bağlı olduğunuz gerçeğiyle aldatılmış hissediyorum. IMHO da öyle değildi; ama en iyi yanıtı aldım: Açıkçası önyargılıyım :-)
JB

Eh, printf () kullanımından dolayı C prolog / epilog kullanımına dolaylı olarak izin verildiğini söyleyebiliriz. C prolog / epilogunu atlarsanız libc işlevleri her zaman güvenilir davranmaz. Aslında sistemimde, çıktıyı bir dosyaya bağlarsam sürümünüz çalışmaz, çünkü stdout sadece C epilog kodunda temizlenir. (Bunun yerine, bir sistem aramasının etrafındaki bir sarıcı olan write () kullansaydık, her iki şekilde de işe
yarardı

Şimdi oldukça uzun zaman oldu, ama C fonksiyonlarının izin verilmesinin benim için bir sürpriz olduğunu hatırlıyorum: problemi kulağa saf olmayan bir şey yaptı. OP de uzun zamandır ortalıkta yok; şimdi açıklama istemek zor olacak.
JB

printfABI'nin argümanlarını yığın üzerinde tıkamasına izin verdiğini unutmayın . callTekrar söylemek ve aynı argümanları beklemek teknik olarak güvenli değil , ancak pratikte işe yarıyor çünkü gcc / clang hiçbir zaman sıfırlama alanı AFAIK gibi argüman yuvalarını kullanmıyor.
Peter Cordes

Ayrıca, genel printfolarak _start(örneğin statik bir ikili dosyada) çağrı yapmak güvenli değildir , bu nedenle bir mainyerine bir yazmak için iyi bir argüman _start. Bu yanıt , libc'yi statik veya dinamik ikili dosyalardan bağlamanın çeşitli yollarını açıklar. (Linux dinamik ikili, kullanmak, böylece dinamik bağlayıcı, glibc en başlatıcı işlevlerini çalışacaktır printfdan _startgiriş noktasında, ama bu IIRC cygwin üzerinde bir durum değildir.)
Peter Cordes

1

Önyüklenebilir ASM, 660 bayt

[bits 16]
mov ax,07C0h
mov ds,ax 
mov ah,0
mov al,03h 
int 10h
mov si,code
call p 
jmp $
p:mov ah,0Eh
r:lodsb
cmp al,0
je d
cmp bx,0x42
jne s
c:int 10h
jmp r
s: cmp al,94 
je re
cmp al,63
je q
jmp c
q:mov al,34
jmp c
re:push si
mov bx,0x42
mov si,code
call p 
mov bx,0
pop si
jmp p 
d:ret
code:db "[bits 16]\mov ax,07C0h\mov ds,ax\mov ah,0\mov al,03h\int 10h\mov si,code\call p\jmp $\p:mov ah,0Eh\r:lodsb\cmp al,0\je d\cmp bx,0x42\jne s\c:int 10h\jmp r\s:cmp al,94\je re\cmp al,63\je q\jmp c\q:mov al,34\jmp c\re:push si\mov bx,0x42\mov si,code\call p\mov bx,0\pop si\jmp p\\d:ret\\code:db ?^?\times 510-($-$$) db 0\dw 0xAA55"
times 510-($-$$) db 0
dw 0xAA55

Aslında jdiez17 tarafından, gerçekten senin tarafından golf .


0

x86-64, Sistem V AMD64 ABI, GASM: 432

.att_syntax noprefix
.globl main
main:
pushq rbp
movq rsp, rbp
mov $.Cs, rdi
mov $0xa, rsi
mov $0x22, edx
mov $.Cs, ecx
mov $0x22, r8d
mov $0xa, r9d
xor eax, eax
call printf
xor eax, eax
leave
ret
.Cs: .string ".att_syntax noprefix
.globl main
main:
pushq rbp
movq rsp, rbp
mov $.Cs, rdi
mov $0xa, rsi
mov $0x22, edx
mov $.Cs, ecx
mov $0x22, r8d
mov $0xa, r9d
xor eax, eax
call printf
xor eax, eax
leave
ret%c.Cs: .string %c%s%c%c"

1
İşlenenler arasındaki virgülden sonra boşluk bırakmanız gerekmez. xor eax,eaxProgramınızın çıkış durumunu umursamıyorsanız da hiç ihtiyacınız yok. Sıfır dışında bir durumla çıksa bile kendini yazdırır. Bunun pushyerine de kullanabilirsiniz pushq. Aslında, neden yığın çerçeve bile yapıyorsunuz? push rbp/ mov rsp, rbpVe tuşunu bırakın leave. Daha kısa etiket adları da kullanabilirsiniz. .Cs1 iyi olduğunda 3 karakterdir.
Peter Cordes

Bundan sonra, .att_syntax noprefixmuhtemelen artık kendisi için ödeme yapmıyor. .intel_syntax noprefixbu altı $öneki de bırakmanıza izin verir . ama muhtemelen buna değmez. ( lea ecx,.CsIntel sözdizimi yerine kullanabilirsiniz mov ecx,offset .Cs)
Peter Cordes

0

TAL

push puts
push \100
push {push puts
push \100
push {@}
dup
strmap
invokeStk 2}
dup
strmap
invokeStk 2

Yürütmek için, ::tcl::unsuppoted::assemblebağımsız değişken olarak kodla çağırın .
Sadece Tcl 8.6.


3
Bayt sayısını eklemelisiniz.
MD XF

0

80x86 TASM, 561 bayt

MODEL TINY
.CODE
.STARTUP
DB 177
DB 076
DB 186
DB 044
DB 001
DB 172
DB 180
DB 036
DB 179
DB 004
DB 191
DB 080
DB 001
DB 079
DB 136
DB 037
DB 212
DB 010
DB 004
DB 048
DB 134
DB 196
DB 075
DB 117
DB 244
DB 180
DB 009
DB 205
DB 033
DB 178
DB 071
DB 226
DB 228
DB 178
DB 038
DB 205
DB 033
DB 195
DB 013
DB 010
DB 069
DB 078
DB 068
DB 036
DB 077
DB 079
DB 068
DB 069
DB 076
DB 032
DB 084
DB 073
DB 078
DB 089
DB 013
DB 010
DB 046
DB 067
DB 079
DB 068
DB 069
DB 013
DB 010
DB 046
DB 083
DB 084
DB 065
DB 082
DB 084
DB 085
DB 080
DB 013
DB 010
DB 068
DB 066
DB 032
END
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.