Quine Bahasa Majelis

20

Tulis quine bahasa assembly yang sesingkat mungkin .

Gunakan ISA yang Anda inginkan, kecuali jika ada print-quineinstruksi atau yang setara. Contohnya termasuk x86, MIPS, SPARC, MMIX, IBM BAL, MIX, VAX, JVM, ARM, dll.

Anda dapat menautkan ke _printffungsi pustaka standar C (atau setara Java untuk bytecode JVM) untuk I / O.

Panjang akan dinilai berdasarkan jumlah instruksi dan ukuran segmen data. Solusi harus mengandung setidaknya dua instruksi.

Quine harus mencetak kode rakitan , bukan kode rakitan mesin.

Hoa Long Tam
sumber
3
Oh wow, ini kedengarannya seperti orang yang tangguh
pengecut anonim

Jawaban:

20

x86 Linux, AT&T sintaks: 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"

(Saya kompilasi dengan ini gcc -nostartfiles -lc quine.S -o quine:)

JB
sumber
Itu menyedihkan, sekarang :-(
Joey
1
Saya biasanya mengatakan "alat yang tepat untuk pekerjaan itu", tetapi sekali lagi, ini rasanya tidak benar: D
JB
Tampaknya lebih benar daripada milikku, meskipun ;-)
Joey
5

JVM Bytecode Assembly (via 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

Sedihnya, Jasmin tidak mengizinkan banyak trik bagus seperti yang ilasmdiizinkan Microsoft . Tetapi JVM memiliki total enamdup instruksi berbeda yang melakukan segala macam hal menyenangkan. Menyusun ulang item pada tumpukan adalah sesuatu .NET sepertinya tidak mendukung.

Bagaimanapun, saya kira tidak satu pun dari dua entri saya adalah pesaing serius untuk kode terpendek tapi saya kira sulit untuk membuatnya lebih pendek. Karena itu hanya untuk kelengkapan :-)

Versi yang dikomentari dengan info tentang apa yang ada di tumpukan:

.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

Sejarah:

  • 2011-02-07 02:09 (990) - Versi pertama yang berfungsi.
  • 2011-02-07 02:11 (960) - ldclebih pendek dari bipushatau iconst_*.
  • 2011-02-07 02:30 (952) - Siapa bilang saya perlu mewarisi dari java.lang.Object? Nama kelas lain jauh lebih pendek :-)
Joey
sumber
4

gas untuk x86 Linux (89 byte, tujuh instruksi)

Secara teknis, ini curang.

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

Simpan dalam nama file adan kumpulkan dengan perintah berikut untuk membuat executable bernama a.out.

as -o a.o ; ld a.o

Arahan .incbinmencakup file kata demi kata di lokasi saat ini. Jika Anda menggunakan ini untuk memasukkan kode sumber itu sendiri, Anda mendapatkan quine yang bagus.

FUZxxl
sumber
3

Windows .COM Format: 307 karakter

Merakit, menggunakan A86, hingga 51 byte. Tidak memerlukan pustaka eksternal selain dari fungsi DOS Int21 AH = 9 (tulis string ke stdout).

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
Mendesis
sumber
Saya khawatir saya menghitung 357 byte. (dan program Anda benar-benar menghasilkan 408) Implementasi yang bagus. Anda mungkin ingin memasukkan sumber perakitan un-db'd sehingga pemirsa lain dapat melihat secara langsung.
JB
@ JK: Saya tidak memasukkan CR \ NL. Melihat itu sekarang, saya benar-benar harus meletakkan data ke dalam satu baris db. Itu akan membuatnya lebih kecil.
Skizz
3

NASM, 223 byte

%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

Mengalahkan jawaban yang diterima!

MD XF
sumber
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}

Satu baris, tidak ada garis putus di akhir.

Versi pertama yang diformat dan dikomentari (meskipun bukan quine lagi) - tidak mungkin saya menyimpang banyak dari konsep umum:

.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
}

Sejarah :

  • 2011-02-06 16:48 (727) - Versi kerja pertama.
  • 2011-02-06 17:14 (723) - Saya tidak perlu spasi setelah string literal.
  • 2011-02-06 17:21 (691) - duplebih pendek dari menulis ldloc.1setiap saat.
  • 2011-02-06 17:24 (669) - Saya tidak butuh spasi setelahnya huruf apa pun dan hal-hal seperti ldloc.1dapat ditulis ldloc 1untuk membuat token terakhir menjadi huruf. Bytecode yang dihasilkan cenderung lebih besar, tapi ini tentang kode assembler jadi saya tidak peduli :-)
  • 2011-02-06 17:34 (623) - Saya tidak perlu object[]sebagai variabel lokal; Saya bisa melakukan semua itu di stack secara langsung. Bagus.
Joey
sumber
Sepertinya Anda telah menghapus objek [] dari versi yang tidak diformat, tetapi bukan yang diformat ...
Aurel Bílý
@ Aurel: Memang, seperti yang disebutkan, format adalah versi pertama. Idenya masih sama sehingga saya tidak akan memperbaruinya lagi.
Joey
2

gas untuk Linux x86, 184 176 byte

.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"

Bangun dengan gcc -m32 -o a.out quine.S. (Ini -m32opsional jika OS Anda sudah 32-bit.)

Diedit untuk menambahkan: Jika kita memodifikasi aturan agar diizinkan putsdipanggil, printfmaka itu dapat dilakukan dalam 182 174 byte:

.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"

(Perhatikan bahwa yang ini, tidak seperti yang sebelumnya, memiliki baris baru yang mengakhiri.)

kotak roti
sumber
Saya menghargai kekurangannya. Tapi saya merasa tertipu oleh fakta bahwa selain printf / put, Anda benar-benar bergantung pada prolog / epilog C standar, yang tidak diperbolehkan secara eksplisit. Dan IMHO tidak dimaksudkan untuk menjadi; tapi saya punya jawaban teratas: jelas saya bias :-)
JB
Yah, orang bisa berpendapat bahwa menggunakan prolog C / epilog secara implisit diizinkan, karena menyebutkan menggunakan printf (). Fungsi libc tidak selalu berperilaku andal jika Anda mem-bypass prolog / epilog. Sebenarnya di sistem saya, versi Anda tidak berfungsi jika saya menyalurkan output ke file, karena stdout hanya akan memerah dalam kode C epilog. (Seandainya kita menggunakan write (), yang hanya
membungkus
Sudah cukup lama sekarang, tapi sepertinya saya ingat fungsi C yang diizinkan adalah kejutan bagi saya saat itu: itu memang membuat masalah terdengar tidak murni. OP juga sudah lama tidak ada; akan sulit untuk meminta klarifikasi sekarang.
JB
Perhatikan bahwa ABI memungkinkan printfuntuk mengalahkan argumennya di stack. Secara teknis tidak aman hanya calldengan sekali lagi dan mengharapkan args yang sama, tetapi bekerja dalam praktik karena gcc / clang tidak pernah menggunakan slot args sebagai ruang awal, AFAIK.
Peter Cordes
Juga, secara umum tidak aman untuk menelepon printfdari _start(misalnya dalam biner statis), jadi itu adalah argumen yang baik untuk menulis amain bukan a _start. Jawaban ini menjelaskan berbagai cara menghubungkan libc dari binari statis atau dinamis. (Dalam biner dinamis Linux, tautan dinamis akan menjalankan fungsi inisialisasi glibc, sehingga Anda dapat menggunakan printfdari _starttitik masuk, tetapi itu tidak terjadi pada cygwin IIRC.)
Peter Cordes
1

ASM yang dapat di-boot, 660 byte

[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

Awalnya oleh jdiez17 , bermain golf dengan benar.

MD XF
sumber
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"
lxgr
sumber
1
Anda tidak perlu spasi setelah koma di antara operan. Dan Anda tidak perlu xor eax,eaxsama sekali jika Anda tidak peduli dengan status keluar dari program Anda. Itu masih mencetak sendiri, bahkan jika itu keluar dengan status tidak nol. Anda juga dapat menggunakan pushbukan pushq. Sebenarnya, mengapa Anda bahkan membuat bingkai stack sama sekali? Jatuhkan push rbp/ mov rsp, rbpdan leave. Anda juga bisa menggunakan nama label yang lebih pendek. .Csadalah 3 karakter ketika 1 akan baik-baik saja.
Peter Cordes
Setelah itu, .att_syntax noprefixmungkin tidak membayar untuk dirinya sendiri lagi. .intel_syntax noprefixakan membiarkan Anda menjatuhkan enam $awalan itu juga. tapi mungkin masih belum sepadan. (Anda bisa menggunakan lea ecx,.Cssintaks intel 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

Untuk menjalankannya, panggil ::tcl::unsuppoted::assembledengan kode sebagai argumen.
Tcl 8.6 saja.

Johannes Kuhn
sumber
3
Anda harus memasukkan jumlah byte.
MD XF
0

80x86 TASM, 561 byte

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
MD XF
sumber