ภาษาแอสเซมบลีควิน


20

เขียนไปได้ที่การชุมนุมภาษาที่สั้นที่สุดควิน

ใช้ ISA ใด ๆ ที่คุณต้องการเว้นแต่จะมีprint-quineคำสั่งหรือสิ่งที่เทียบเท่า ตัวอย่างเช่น x86, MIPS, SPARC, MMIX, IBM BAL, MIX, VAX, JVM, ARM และอื่น ๆ

คุณสามารถเชื่อมโยงกับ_printfฟังก์ชั่นของไลบรารีมาตรฐาน C (หรือ Java เทียบเท่ากับ JVM bytecode) สำหรับ I / O

ความยาวจะถูกตัดสินทั้งตามจำนวนการสอนและขนาดของส่วนข้อมูล วิธีแก้ไขจะต้องมีคำแนะนำอย่างน้อยสองคำ

ควินินควรพิมพ์รหัสการประกอบไม่ใช่รหัสเครื่องที่ประกอบ


3
โอ้ว้าวเสียงนี้ดูเหมือนจะเป็น
คนขี้ขลาด

คำตอบ:


20

x86 Linux, AT&T ไวยากรณ์: 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"

(ผมเรียบเรียงด้วยนี้gcc -nostartfiles -lc quine.S -o quine)


ตอนนี้ :-(
Joey

1
ฉันมักจะพูดว่า "เครื่องมือที่เหมาะสมสำหรับงาน" แต่แล้วอีกครั้งที่นี่มันรู้สึกไม่ถูกต้อง: D
JB

ดูเหมือนว่าจะถูกกว่าของฉันแม้ว่า ;-)
Joey

5

JVM Bytecode Assembly (ผ่าน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

น่าเศร้าที่ Jasmin ไม่อนุญาตให้ใช้กลอุบายที่ดีเท่าที่ไมโครซอฟท์ilasmอนุญาต แต่ JVM มีทั้งหมดหกdupคำสั่งต่าง ๆที่ทำสิ่งสนุก ๆ การเรียงลำดับรายการในสแต็กเป็นสิ่งที่. NET ไม่สนับสนุน

ไม่ว่าในกรณีใดฉันเดาว่าไม่มีรายการใดในสองรายการของฉันที่เป็นคู่แข่งร้ายแรงสำหรับรหัสที่สั้นที่สุด แต่ฉันเดาว่ามันยากที่จะทำให้รายการสั้นลงมาก ดังนั้นเพียงเพื่อความสมบูรณ์ :-)

เวอร์ชันที่มีความคิดเห็นพร้อมข้อมูลเกี่ยวกับสิ่งที่อยู่ในสแต็ก:

.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

ประวัติความเป็นมา:

  • 2011-02-07 02:09 (990) - รุ่นทำงานครั้งแรก
  • 2011/02/07 02:11 (960) - ldcสั้นกว่าหรือbipushiconst_*
  • 2011-02-07 02:30 (952) - ใครบอกว่าฉันต้องสืบทอดจาก java.lang.Object ชื่อชั้นอื่น ๆ สั้นกว่ามาก :-)

4

gas สำหรับ x86 Linux (89 bytes, เจ็ดคำแนะนำ)

ในทางเทคนิคนี่เป็นการโกง

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

บันทึกในไฟล์ชื่อaและประกอบกับคำสั่งต่อไปนี้เพื่อสร้างไฟล์ที่เรียกใช้งานa.outได้

as -o a.o ; ld a.o

คำสั่ง.incbinรวมถึงคำต่อคำไฟล์ที่ตำแหน่งปัจจุบัน หากคุณใช้สิ่งนี้เพื่อรวมซอร์สโค้ดเองคุณจะได้รับ quine ที่ดี


3

รูปแบบ Windows. COM: 307 ตัวอักษร

Assembles โดยใช้ A86 ถึง 51 ไบต์ ไม่จำเป็นต้องใช้ไลบรารีภายนอกนอกเหนือจากฟังก์ชั่น DOS Int21 AH = 9 (เขียนสตริงลงใน 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

ฉันกลัวว่าจะนับ 357 ไบต์ (และโปรแกรมของคุณส่งออก 408) การใช้งานที่ดี คุณอาจต้องการที่จะรวมแหล่งที่มาประกอบที่ไม่ได้ db'd เพื่อให้ผู้ชมคนอื่นได้ดูโดยตรง
JB

@JB: ฉันไม่ได้รวม CR \ NL มองไปที่ตอนนี้ฉันควรจะใส่ข้อมูลลงในบรรทัด db เดียว นั่นจะทำให้มันเล็กลง
Skizz

3

NASM ขนาด 223 ไบต์

%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

เอาชนะคำตอบที่ยอมรับ!


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}

บรรทัดเดียวไม่มีการแบ่งบรรทัดในตอนท้าย

จัดรูปแบบและแสดงความคิดเห็นเวอร์ชันแรก (แม้ว่าจะไม่ใช่ควินอีกต่อไป) - ไม่น่าเป็นไปได้ที่ฉันจะเบี่ยงเบนไปจากแนวคิดทั่วไป:

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

ประวัติความเป็นมา :

  • 2011-02-06 16:48 (727) - รุ่นที่ใช้งานครั้งแรก
  • 2011-02-06 17:14 (723) - ฉันไม่ต้องการช่องว่างหลังจากตัวอักษรสตริง
  • 2011-02-06 17:21 (691) - dupสั้นกว่าการเขียนldloc.1ทุกครั้ง
  • 2011/02/06 17:24 (669) - ฉันไม่จำเป็นต้องมีช่องว่างหลังจากการใด ๆที่แท้จริงและสิ่งที่ต้องการldloc.1สามารถเขียนเป็นldloc 1ที่จะทำให้สุดท้ายโทเค็นตัวอักษร โค้ดไบต์ที่ได้นั้นน่าจะมีขนาดใหญ่กว่า แต่มันเกี่ยวกับรหัสแอสเซมเบลอร์ดังนั้นฉันจึงไม่สนใจน้อยกว่า :-)
  • 2011-02-06 17:34 (623) - ฉันไม่ต้องการobject[]ตัวแปรท้องถิ่น ฉันสามารถทำทุกอย่างบนสแต็กได้โดยตรง ดี

ดูเหมือนว่าคุณได้นำวัตถุ [] จากรุ่นที่ยังไม่ฟอร์แมต แต่ไม่ได้จัดรูปแบบหนึ่ง ...
Aurel Bílý

@Aurel: แน่นอนตามที่ระบุไว้การจัดรูปแบบเป็นรุ่นแรกมาก แนวคิดนี้ยังคงเหมือนเดิมดังนั้นฉันจะไม่อัปเดตอีกครั้ง
Joey

2

gas สำหรับ x86 Linux, 184 176 bytes

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

gcc -m32 -o a.out quine.Sรูปร่างด้วย ( -m32ตัวเลือกนี้เป็นตัวเลือกหากระบบปฏิบัติการของคุณเป็น 32 บิตแล้ว)

แก้ไขเพื่อเพิ่ม:หากเราปรับเปลี่ยนกฎเพื่ออนุญาตให้putsเรียกแทนprintfได้สามารถทำได้ใน182 174 ไบต์:

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

(โปรดทราบว่าอันนี้ซึ่งแตกต่างจากอันก่อนหน้านี้มีการขึ้นบรรทัดใหม่)


ฉันรู้สึกซาบซึ้ง แต่ฉันรู้สึกว่าถูกโกงโดยความจริงที่ว่านอกเหนือจากการพิมพ์ / ใส่แล้วคุณขึ้นอยู่กับมาตรฐาน C prolog / epilog ซึ่งไม่ได้รับอนุญาตอย่างชัดเจน และ IMHO ไม่ได้ตั้งใจจะเป็น แต่ฉันก็ได้คำตอบที่ดีที่สุด: เห็นได้ชัดว่าฉันลำเอียง :-)
JB

ทีนี้ใคร ๆ ก็ยืนยันว่าการใช้ C prolog / epilog นั้นได้รับอนุญาตโดยปริยายเนื่องจากมีการกล่าวถึงการใช้ printf () ฟังก์ชั่น libc ไม่ได้ทำงานอย่างน่าเชื่อถือเสมอไปถ้าคุณข้าม C prolog / epilog อันที่จริงแล้วในระบบของฉันเวอร์ชั่นของคุณไม่ทำงานถ้าฉันไปป์เอาท์พุทไปยังไฟล์เพราะ stdout จะถูกลบทิ้งในรหัส epilog ของ C เท่านั้น (ถ้าเราใช้เขียนแทน () ซึ่งเป็นเพียงเสื้อคลุมรอบตึกระฟ้ามันก็จะทำงานได้ทั้งสองวิธี)
27712

เป็นเวลานานแล้ว แต่ฉันดูเหมือนจะจำได้ว่าฟังก์ชั่น C ที่ได้รับอนุญาตเป็นเรื่องแปลกใจสำหรับฉันในตอนนั้น: มันทำให้ปัญหาเสียงไม่บริสุทธิ์ OP ไม่ได้อยู่ในวงการมานานแล้วเช่นกัน มันจะยากที่จะขอคำชี้แจงในขณะนี้
JB

โปรดทราบว่า ABI อนุญาตให้printfปิดบังส่วนบนของสแต็ก มันไม่ปลอดภัยในทางเทคนิคที่จะใช้callมันอีกครั้งและคาดหวังว่า args เดียวกัน แต่ใช้งานได้จริงเพราะ gcc / clang ไม่เคยใช้สล็อต args เป็นพื้นที่รอยขีดข่วน AFAIK
Peter Cordes

นอกจากนี้โดยทั่วไปก็ไม่ปลอดภัยที่จะเรียกprintfจาก_start(เช่นในไบนารีคงที่) เพื่อให้เป็นอาร์กิวเมนต์ที่ดีสำหรับการเขียนแทน main คำตอบนี้อธิบายวิธีการต่างๆในการเชื่อมโยง libc จากไบนารีแบบคงที่หรือแบบไดนามิก (ในไบนารีแบบไดนามิกของ Linux ตัวเชื่อมโยงแบบไดนามิกจะเรียกใช้ฟังก์ชั่นเริ่มต้นของ glibc ดังนั้นคุณสามารถใช้จากจุดเข้าใช้งานได้แต่นั่นไม่ใช่กรณีของ cygwin IIRC)_startprintf_start
Peter Cordes

1

ASM ที่บูตได้, 660 ไบต์

[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

สร้างสรรค์โดยjdiez17 , golfedโดยของคุณอย่างแท้จริง


0

x86-64, System 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
คุณไม่ต้องการช่องว่างหลังเครื่องหมายจุลภาคระหว่างตัวถูกดำเนินการ และคุณไม่จำเป็นxor eax,eaxเลยถ้าคุณไม่สนใจสถานะทางออกของโปรแกรมของคุณ มันยังคงพิมพ์ตัวเองแม้ว่าจะออกด้วยสถานะที่ไม่เป็นศูนย์ นอกจากนี้คุณยังสามารถใช้แทนpush pushqจริงๆแล้วทำไมคุณถึงสร้างเฟรมสแต็คเลยล่ะ? วางpush rbp/ และmov rsp, rbp leaveคุณสามารถใช้ชื่อป้ายกำกับที่สั้นกว่านี้ได้ .Csคือ 3 ตัวอักษรเมื่อ 1 จะดี
Peter Cordes

หลังจากนั้น.att_syntax noprefixอาจไม่จ่ายเองอีกต่อไป .intel_syntax noprefixจะให้คุณดรอป$คำนำหน้าทั้งหกด้วย แต่อาจจะไม่คุ้มค่า (คุณสามารถใช้lea ecx,.Csแทนรูปแบบ intel-syntax 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

หากต้องการดำเนินการให้โทร::tcl::unsuppoted::assembleด้วยรหัสเป็นอาร์กิวเมนต์
Tcl 8.6 เท่านั้น


3
คุณควรรวมจำนวนไบต์
MD XF

0

80x86 TASM, 561 ไบต์

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.