Роздрукуйте фразу "І вона сказала:" Але це його ". Використовуючи лише алфавіт


50

Роздрукуйте фразу, And she said, 'But that's his.'використовуючи лише такі символи: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ Ні пунктуаційних, ні алфавітних символів. Ви можете використовувати будь-яку мову програмування. Пробіл повністю дозволений. Найкоротша програма виграє.


Що про пробіли у виході? (ведучий / трейлінг?)
attinat

2
Дарн, мій езоланг не може завершитись, тому що немає можливості отримувати вихід тільки a-zA-Z. Теоретично я міг використовувати wобряд і Eваль для створення необхідних інструкцій, але жоден з них не +-*,%'"може бути побудований без використання (принаймні) одного з +-*,%'"0-9.
Draco18s

10
(programmer-of (language 'lisp))це не любить цього.
MatthewRock

4
Потрібно визнати, спочатку я не вважав це особливо цікавим, але поєднання повторних та унікальних символів насправді зробило щось цікаве для оптимізації (особливо на мові стека!). Дуже хороша.
brhfl

1
Чи можете ви уточнити, чи дозволяється додаткове пробіл у висновку ? Подобаються додаткові лінійки? Або лише пробіл у джерелі , а також алфавітні символи. Є відповідь Befunge, яка друкує додатковий новий рядок.
Пітер Кордес

Відповіді:


75

Пробіл , 417 414 349 265 байт

265 байт завдяки Кевіну Крейссену

  							
  				   
   		 	
   		
   	 
  		   		 
 	  		
 	  		 
   			 
  		 	
   	 
 	  	 
 	  		 
 	  	
   				
  		  	  
  							
 	  	  
  				 	 
  		 
   		
  		 	
   		 	
 	  	 	
  		
   	 
 	  		
 	  		
  		 
   	   
  		  	 	

  
   		  		 
	   	
  
 


Спробуйте в Інтернеті!

Пояснили:

[S S T  T   T   T   T   T   T   N
_Push_-63_'][S S T  T   T   T   S S S N
_Push_-53_.][S S S T    T   S T N
_Push_13_s][S S S T T   N
_Push_3_i][S S S T  S N
_Push_2_h][S S T    T   S S S T T   S N
_Push_-70_space][S T    S S T   T   N
_Copy_0-based_3rd_s][S T    S S T   T   S N
_Copy_0-based_6th_'][S S S T    T   T   S N
_Push_14_t][S S T   T   S T N
_Push_-5_a][S S S T S N
_Push_2_h][S T  S S T   S N
_Copy_0-based_2nd_t][S T    S S T   T   S N
_Copy_0-based_6th_space][S T    S S T   N
_Copy_0-based_1st_t][S S S T    T   T   T   N
_Push-15_u][S S T   T   S S T   S S N
_Push_-36_B][S S T  T   T   T   T   T   T   N
_Push_-63_'][S T    S S T   S S N
_Copy_0-based_4th_space][S S T  T   T   T   S T S N
_Push_-58_,][S S T  T   S N
_Push_-2_d][S S S T T   N
_Push_3_i][S S T    T   S T N
_Push_-5_a][S S S T T   S T N
_Push-13_s][S T S S T   S T N
_Copy_0-based_3rd_space][S S T  T   N
_Push_-1_e][S S S T S N
_Push_2_h][S T  S S T   T   N
_Copy_0-based_3rd_s][S T    S S T   T   N
_Copy_0-based_3rd_space][S S T  T   S N
_Push_-2_d][S S S T S S S N
_Push_8_n][S S T    T   S S T   S T N
_Push_-37_A][N
S S N
_Create_Label_LOOP][S S S T T   S S T   T   S N
_Push_102][T    S S S _Add][T   N
S S _Print_as_character][N
S N
N
_Jump_to_Label_LOOP]

100
Whitespace is completely allowed.Я бачу, ви сприйняли це буквально.
Бенджамін Уркхарт

3
Ти перебив мене до цього .. Хоча досить багато речей можна пограти в гольф. :) Ви можете видалити трейлінг NNNдля виходу, оскільки він вже припиняється з помилкою, коли ви робите додавання перед print_char, тому він навіть не з’явиться після Jump_to_Label. Крім того, навіщо зберігати 63на початку та отримувати його у циклі? Ви можете просто натиснути його перед додаванням замість цього. І чому ж Label-nr TTSSSSTN? Мітка навіть може бути порожньою, тому достатньо лише NSSNстворити мітку та NSNNперейти до мітки, коли ви використовуєте лише одну мітку.
Kevin Cruijssen

1
318 байт із змінами, які я запропонував вище. Ось та сама програма з доданим підсвічуванням. І як ви вирахували постійну величину 63? Я не впевнений на 100%, що це найкоротша константа можлива тут. Якщо це так, щось не в порядку з моєю програмою постійної генерації, яку я написав для попереднього завдання. :)
Kevin Cruijssen

1
Так, я мав рацію. Constant 102є найбільш ефективним: 281 байт (або тут з виділенням ). (ПРИМІТКА. Я також використав одну копію, щоб зберегти 4 байти для проміжку між ними ehs dnA(скопійовано з пробілу між ними dias ehs).
Кевін Круїйсен

3
Гаразд, зараз я закінчив. :) 265 байт (або тут з виділенням ). Додано кілька додаткових примірників. ( Тут відповідна порада пробілів .)
Кевін Круїссен

62

Perl 5 , 133 102 95 байт

s qqAnd she saidZ ZBut thatZs hisZZGjGGfq x
s qZqchr oct oct oct ord chopqge x
y qGjfqqdx
print

Спробуйте в Інтернеті!

Пояснення:

Регекси, друк та рубання застосовуються до змінної $_за замовчуванням.

s qqAnd she saidZ ZBut thatZs hisZZGjGGfq

Замінює порожній рядок на And she saidZ ZBut thatZs hisZZGjGGf.

s qZqchr oct oct oct ord chopqge

Замінює кожного Zз результатом евальвації chr oct oct oct ord chop. Це видаляє останній символ символу $_, бере його код ключа, інтерпретує його як вісімковий тричі і перетворює його назад у символ. Наприклад, j→ 106 → 70 → 56 → 46 → ..

У зв'язку з тим, як працює заміна, зміни, $_які трапляються під час оцінки заміни, втрачаються, так $_це і зараз And she said, 'But that's his.'GjGGf.

y qGjfqqd

Видаляє всі G, jі fв $_.


26
Не знаючи Perl, схоже, ви щойно намагалися ввести речення, але потрапили в декілька боїв зі своєю кішкою
popctrl

2
Це, можливо, найкрасивіший фрагмент коду, який я коли-небудь бачив, написаного на цьому веб-сайті, і я говорю це як хтось, хто знає Perl.
Сільвіо Майоло

1
Пов'язані, але ви можете замінити printз sayна -2 символів. Поточний мета-консенсус говорить, що прапори командного рядка -M5.010не враховують кількість байтів.
Сільвіо Майоло

34

> <> , 916 915 903 байт

Спочатку я вважав, що рішення в> <> неможливо, але потім зрозумів ... кому потрібні умови або логічний контроль? : D

fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffloffffffffffffffffffffffffffffffffffffffffffffflopppgloppppppppppppppppppppppggloffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflopppggloploppppppppppppppppppppppploffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflopppppplofffffffflopggloppppppppppppppppppgglopppplofffffffloffffffffffffffffffffffffffflofffffffffffffffffffffffffffffffffffffffffffffffffffloglopppppppppppppppppppppppppppplofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflopppploppgloffffffffffffffffffflopppppppppppppppppppppppppgglofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflopppppppppppppppppppppppppppgglofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflofloffffffffffloppppppppppppppppppppppploppgloio

Спробуйте в Інтернеті

Я кілька разів натискаю цифри (число 15) до стеку, потім натискаю довжину стека і друкую символ із цим значенням ASCII. Якщо мені потрібно зменшити довжину стека, я стискаю стек на три значення одночасно, використовуючи pодне за одним, використовуючи, gякщо я перебуваю в межах трьох цілей. Програма закінчується викликом i(введенням), який натискає, -1оскільки немає вводу, а потім друкує його, щоб викликати помилку.

Це програма Python 3, яку я використовував для створення рішення, коли я думав, як це зробити:

s = "And she said, 'But that's his.'"
L = [0]+[ord(c) for c in s]
#print(L)
M = L[1:]+[0]
D = [x[1]-x[0] for x in zip(L,M)]
#print(D)
while D:
	n=D.pop(0)
	if not D:print('io',end='');exit()
	if n>0:print('f'*n,end='lo')
	else:
		while n<-2:print('p',end='');n+=3
		print('g'*-n,end='lo')

Спробуйте в Інтернеті


5
Це правильний контрапункт рішення пробілу! Отримайте +1 від мене, я також ціную програму, що генерує ...
Франческо

Останній розділ може бути повністю вилучений з обережним використанням p: створити 59 в стеці при русі вгору від простору до sдюйму said, а потім помістити його в коді на шляху вниз від dдо ,. (Зауважимо, що (15,15) до цього моменту є 15.)
Нітродон

Насправді ви можете зловживати lі pвводити кілька корисних символів у прямокутник (10,10) - (15,15), а потім витягувати їх gтам, де зручніше.
Нітродон

Це дійсно гарна ідея. Дуже важко думати про <<> таким чином. Це як кодування з BF
mbomb007

Я опублікував власну відповідь: codegolf.stackexchange.com/a/186916/69059
Nitrodon

28

8086 Збірка на IBM PC, 1463 845 664 байт

Уточнення: Фактичним джерелом мови збірки є запис, а не створений машинний код.

Складність полягає в тому, що більшість інструкцій x86 (наприклад, ADD, SUB, JMP, умовні стрибки, доступ до пам'яті) мають два аргументи, і тому потрібна кома або потрібна адреса пам'яті. Отже, ми не можемо використовувати додавання, віднімання, ifs чи циклі!

Під час моєї першої спроби я зміг "побудувати" числа, використовуючи комбінацію приросту, зменшення, множення, ділення, байт-трюків та незрозумілих інструкцій BCD (наприклад, AAA, DAS). Після цього я зрозумів, що ця ідея може бути використана для створення коду, що самоперевіряється та що змінюється.

  • Спроба 1. (1463 байти)

    Використовували доступні вказівки для побудови кодів ASCII та адреси 0xb800 буферного екрану. Обчислення кожного символу в послідовності гольфували вручну.

  • Спроба 2. (не завершена)

    Зрозуміло, що існує опкод для кожного цілого числа в діапазоні 0x40-0x5f. Цей асортимент включає AZ. Так, наприклад, INC CX відповідає 0x41 = 'A'. (Ця таблиця опкодів дуже зручна.)

    Я спробував побудувати 3 рядки "даних" і накладати їх один на одного. Перший як є (верхній регістр), другий "змістився" в зону 0x60-0x7f (нижній регістр), а останній "змістився" в зону 0x20-0x3f (пунктуація).

    Код, що самозмінюється, створить цикл або три для повторення даних.

  • Спроба 3. (845 байт)

    Як і в попередньому підході, але для скорочення даних, рядок кодується лише один раз, з "контрольними символами", змішаними для переключення наборів символів.

  • Спроба 4. (664 байти)

    Як позбутися від контрольних символів, які потребують великої кількості виправлених інструкцій, щоб мати справу з розгалуженням? Зважаючи на те, що використовуються лише дві великі літери, я задумався, чи можу я "перевернути" таблицю опкодів, щоб кодувати малі літери, використовуючи діапазон 0x40-0x4f та розділові знаки, використовуючи діапазон 0x90-0x9f (віднімаючи від 0xc0). "A" і "B" можна поставити окремо.

    Однак лише половина опкодів у діапазоні 0x90-0x9f є корисною, і вони не узгоджуються з потрібними. Тоді я подумав, що, можливо, я можу перетасувати їх за допомогою XOR, і знайшов той, який спрацював. І ось воно.

Гольф:

REP LODSB
PUSH CX
PUSH CX
POP AX
INC CH
PUSH CX
POP DI
DEC AX
DEC AX
REPNE SCASB
REPNE SCASB
PUSH DI
REPNE SCASB
PUSH DI
REPNE SCASB
PUSH DI
POP SI
POP DI
DEC DI
LODSB
NOT AL
STOSB
POP CX
DEC CH
LODSB
NOT AL
STOSB
LODSB
AAA
STOSB
INC DI
LODSB
NEG AL
STOSB
LODSB
NOT AL
PUSH AX
PUSH AX
INC SP
POP ES
INC SP
POP DI
LODSB
NOT AL
PUSH AX
POP BX
NEG AL
STOSB
INC DI
LODSB
DEC AL
NEG AL
DIV BH
PUSH AX
POP DI
LODSB
STOSB
RET
DEC BL
PUSH CS
STOSB
PUSH DS
INC DI
INC AX
POP SI
PUSH SP
NOP
INC BP
POP AX
PUSH DI
NOP
INC BP
PUSH BX
POP BX
PUSH SP
PUSHF
NOP
CWD
PUSH DX
INC DI
INC SP
NOP
INC SP
POP AX
PUSH BX
INC SP
CWD
INC BP
NOP
POP AX
POP BX
INC BP
SAHF
CWD
SCASB
INC DX

Зберіть з

nasm golf.asm -o golf.com

та запустіть у DOSBOX (спочатку запустіть CLS). Виглядає так:

Вибірка зразка

Прокоментував:

; ASSUME DS = ES = CS
; ASSUME IP = 0x0100
; true for .COM file

; We treat 0xFE as a special marker that we scan for
; This marks our patch zone and the start of our data

; We also use it as a cheap trick to get a constant 0x1f
; into CX

; 0xFE is the first byte of INC or DEC instructions
; that operate on half-word registers (AL, BL, CH etc.)
; WATCH OUT! Adding these breaks the scan


; Can't assume any register contains zero
; so use this trick to zero out CX
REP LODSB

PUSH CX ; needed later

; zero AX
PUSH CX
POP AX

INC CH
PUSH CX
POP DI ; 0x100, where our code starts

DEC AX
DEC AX ; AL = 0xFE, our marker (AH = 0xFF)

REPNE SCASB ; skip the INC CH above
REPNE SCASB ; find the DEC CH located at 0x10E

; we will later need 0xF, the char count minus the 'A'
PUSH DI ; DI = 0x10F

REPNE SCASB ; find the patch position
PUSH DI

REPNE SCASB ; find the next 0xfe; our data section
PUSH DI
POP SI ; load data from here

POP DI ; store data to the patch position
DEC DI

; patch in XOR
; XOR is 0x34, start with 0xCB
; second byte of DEC BL is 0xCB
LODSB
NOT AL
STOSB

POP CX ; get 0x0f in CX for our strlen
DEC CH

; patch in our XOR arg
; it is 0xF1 (take 0x0E and NOT it)
LODSB ; 0x0E (PUSH CS)
NOT AL
STOSB

; ADD is 0x00 (take 0xAA, apply weird AAA behaviour)
; this also zeroes AH
LODSB ; 0xAA (STOSB)
AAA
STOSB

INC DI ; skip next instruction byte

; LOOP is 0xE2
LODSB ; 0x1E PUSH DS
NEG AL
STOSB


; get b800 in ES (address of screen buffer)
; first get 0x47 in AL (INC DI)
LODSB  ; get 0x47 (INC DI)
NOT AL ; NOT 0x47 = 0xb8
; AX = 0x00b8 (bytes backwards)

PUSH AX
PUSH AX
; stack contains 0xb8 0x00 0xb8 0x00
; stack off-by-1 trick
INC SP
; now POP gives you 0xb800
POP ES
INC SP ;and clean up after ourselves

; store 0 in DI ***** PUSHED AT START OF PROGRAM ***
POP DI


LODSB ; get our magic 0xC0 (0x40 INC AX)
NOT AL
PUSH AX
POP BX

NEG AL ; NOT and +1 to get 0x41 ("A")


; charloop:
STOSB
INC DI
LODSB
DEC AL ; XOR
NEG AL ; modify this into an ADD AL, BL
DIV BH ; modify this to LOOP back to charloop

; doesn't print the last character
; but the last character turns into the address where 'B'
; is supposed to go

PUSH AX
POP DI
LODSB ; "B"
STOSB

; graceful exit this time ;)
RET


; *** DATA SECTION ***

         ; PURPOSE

DEC BL   ; 0xFE marks data section, 0xCB for XOR
PUSH CS  ; for XOR arg
STOSB    ; for ADD
PUSH DS  ; for LOOP
INC DI   ; 0x47 -> for 0xb800

INC AX   ; for magic number but also "A"


POP     SI ;n
PUSH    SP ;d
NOP        ;
INC     BP ;s
POP     AX ;h 
PUSH    DI ;e
NOP        ;
INC     BP ;s
PUSH    BX ;a
POP     BX ;i
PUSH    SP ;d
PUSHF      ;,
NOP        ;
CWD        ;'
PUSH    DX ;B
INC     DI ;u
INC     SP ;t
NOP        ;
INC     SP ;t
POP     AX ;h
PUSH    BX ;a
INC     SP ;t
CWD        ;'
INC     BP ;s
NOP        ;
POP     AX ;h
POP     BX ;i
INC     BP ;s
SAHF       ;.
CWD        ;'

SCASB     ; treated as char but turns into screen address!
INC DX    ; "B"

Гм. Я отримую різні .COM файли з двох джерел складання, починаючи з зміщення 0x3e. Редагувати - Nvm знайшов різницю: рядок 117 у коментованій версії є, INC AXпоки є некомптованим INC AL.
гастропнер

1
Я хочу замість цього побачити повністю алфавітний двійковий файл. :-)
peter ferrie

1
Якщо вам зручно блокувати NASM як асемблер за вибором, ви можете створювати мітки, роблячи label1 dbпо своїй лінії. Це призведе до попередження, але помилки не буде.
гастропнер

1
@gastropner добре, що просто зробить це занадто просто. : P Не знав про це, дякую! Можливо, я повинен перейменувати свою мову як "щось, що можна подати в DEBUG.COM". Що, до речі, я налагоджував це. xD
Artelius

1
@PeterCordes тепер ця модифікується!
Артелій

23

Perl 6 , 1299 1272 1220 1215 байт

Завдяки Grimy за -27 байт.

-52 байти, оскільки нам не потрібні були кролячі вуха.

Завдяки Джо Кінгу за -5 байт.

print chr flip chars i x chars i xx pi
and print lc chr chars NaN x chars cis pi
and print lc chr chars e x e x e
and print chr chars i x e x e x e
and print lc chr flip chars exp i
and print lc chr chars NaN x tau x e x e
and print chr chars chop NaN x e lcm chars e
and print chr chars i x e x e x e
and print lc chr flip chars exp i
and print lc chr flip chars i x chars i xx pi
and print chr chars False x pi x ceiling tau
and print lc chr chars e x e x e
and print chr chars i xx chars NaN x pi
and print chr chars i x e x e x e
and print chr chars chop False x e x e x e
and print chr chars chop NaN xx chars e
and print lc chr chars e x chars False
and print lc chr chars chop e x chars False
and print chr chars i x e x e x e
and print lc chr chars chop e x chars False
and print lc chr chars NaN x tau x e x e
and print lc chr flip chars i x chars i xx pi
and print lc chr chars chop e x chars False
and print chr chars chop False x e x e x e
and print lc chr flip chars exp i
and print chr chars i x e x e x e
and print lc chr chars NaN x tau x e x e
and print chr chars False x pi x ceiling tau
and print lc chr flip chars exp i
and print chr chars NaN xx tau x e
and say chr chars chop False x e x e x e

Спробуйте в Інтернеті!

Виводить рядок із заднім рядком. Якщо ви цього не хочете, замініть останній sayна а print. Ви також можете замінити нові рядки в джерелі пробілами.

Пояснення

Цей код друкує рядок за символом. Кожен символ формується за допомогою подачі у функцію відповідного коду символів та зменшення chrйого lcпри необхідності.

В даний час всі значення генеруються шляхом генерації рядка з правильною кількістю символів у ньому; у деяких випадках кількість символів є зворотним кодом цільового символу. Теоретично слід використовувати математичні функції, такі як logі expбезпосередньо, але мені не було дуже зручно їх використовувати.

Для використання в якості чисел, ми маємо e, piі tau; в правій частині xабо xx, вони неявно закріплені. Усі вони мають 17 символів у своїх рядкових зображеннях, тому ми використовуємо eдля мінімальної кількості символів. У нас також є i(4 символи), False(5 символів) і NaN(3 символи). Ми можемо помножити довжини рядків за допомогою x; xxпомножує один плюс довжину струни на праву частину і додає одну. chopвидаляє один символ із рядка, якщо ми знаходимось один від мети.

Виписки щодо друку пов'язані між собою, використовуючи це and, що має низький пріоритет. Це майже диво, що воно існує; інакше нам доведеться використовувати незаконні крапки з комою.

Я знайшов вирази для персонажів вручну. Можливо, варто їх пошукати програмно, щоб знайти більш короткі вирази.



До речі, @JoKing, ви шукали коротші вирази вручну чи використовували програму для допомоги?
bb94

1
Вручну боюся. Алгоритмічний спосіб, ймовірно, не був би надто складним
Джо Кінг,


@Grimy Розумний, але, на жаль, можливий лише тому, що простір нульової ширини, який ви використовуєте, не є символом пробілу
Jo King

17

Ширина , 66 64 байт

QaaGmwmiimaGcwWiimawAGawmfciiiGaFmAmFiimFGcwAmFiGmaiiGcGamafFiGQ

Спробуйте в Інтернеті!

Друкує для налагодження. Щоб надрукувати stdout, додайте wwдо кінця коду, який з'являється та виводить верхню частину стека.

Пояснення

У Ширині кожна літера співвідноситься з цифрою, виходячи з того, наскільки вона "широка", відповідно до цієї таблиці . Це присвоює кожній букві число від 0 до 9. Потім ці числа використовуються для фактичного виконання коду.

Зокрема, лист, ніж збіги 7, запустить рядковий літерал. Він буде читати набори з двох літер одночасно, поки знову не прочитає оригінальний лист. Кожен набір з двох літер буде перетворений на їхні ширини, прочитані у вигляді десяткового числа між 0 і 99, а символ, який вони рівні, буде їх індексом у наступному рядку:

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~\n\t

Наприклад, індекс !дорівнює 1, тому 01будуть правильні числа ширини. Таким чином, if, iI, jtі т.д. все буде корелювати з строкового літерала з !.

У цьому випадку я переклав 31 символ потрібного виводу на відповідні літери, використовуючи Qяк лапки. Верхня частина стеку друкується для налагодження, коли програма закінчується.


Це найкоротший досі. Я думаю, ти міг би перемогти!
Голубий яструб

14

машинний код x86 (32-бітний), 256 байт

Коли я друкую свій код на консолі кодування 437 сторінки, я бачу таке:

j XI a I a I a jbZ      Q fiQ Gf a f    Q I a I a I a I a h hisZ        Q I a I a I a I a hBP  Z        Q iQ
y       Q  a I a I a I a h thaZ Q I a I a I a Ih ButZ   Q  a I a I a I a fhu fZf        Q iQ g  S       Q  a I a I a I a hsaidZ Q I a I a I a I a hshe Z        Q I a I a I a I a hAnd Z        Q TZBX b 

Він містить декілька символів пробілу, тому тут є той самий код, коли я замінюю всі символи вкладки на всі символи та нерозривні пробіли (з кодом 255) на *:

j XI a I a I a jbZ→Q fiQ Gf a f→Q I a I a I a I a h hisZ→Q I a I a I a I a hBP  Z→Q iQ →→y →Q  a I a I a I a h thaZ→Q I a I a I a Ih ButZ→Q  a I a I a I a fhu fZf→Q iQ g→S →Q  a I a I a I a hsaidZ→Q I a I a I a I a hshe Z→Q I a I a I a I a hAnd Z→Q TZBX*b*

Hexdump:

6a 20 58 49 20 61 20 49 20 61 20 49 20 61 20 6a
62 5a 09 51 20 66 69 51 20 47 66 20 61 20 66 09
51 20 49 20 61 20 49 20 61 20 49 20 61 20 49 20
61 20 68 20 68 69 73 5a 09 51 20 49 20 61 20 49
20 61 20 49 20 61 20 49 20 61 20 68 42 50 20 20
5a 09 51 20 69 51 20 09 09 79 20 09 51 20 20 61
20 49 20 61 20 49 20 61 20 49 20 61 20 68 20 74
68 61 5a 09 51 20 49 20 61 20 49 20 61 20 49 20
61 20 49 68 20 42 75 74 5a 09 51 20 20 61 20 49
20 61 20 49 20 61 20 49 20 61 20 66 68 75 20 66
5a 66 09 51 20 69 51 20 67 09 53 20 09 51 20 20
61 20 49 20 61 20 49 20 61 20 49 20 61 20 68 73
61 69 64 5a 09 51 20 49 20 61 20 49 20 61 20 49
20 61 20 49 20 61 20 68 73 68 65 20 5a 09 51 20
49 20 61 20 49 20 61 20 49 20 61 20 49 20 61 20
68 41 6e 64 20 5a 09 51 20 54 5a 42 58 ff 62 ff

Деякі пояснення, як це працює:

Корисні інструкції:

  • push imm8, push imm16а push imm32потім popгенерують константи. Це також може генерувати нуль (in ah) при натисканні байта ( imm8).
  • and [ecx+32], ah- якщо вважати ах = 0, то байт встановлює нуль. Так буває, що довжина вихідного рядка дорівнює 32, тому код заповнює буфер від кінця до початку.
  • or [ecx+32], edx- якщо припустимо, що вихідний байт встановлений на нуль, це копіює edx(4 байти) на вихід. Я використовую варіант із, dxа не з edxкінця буфера, оскільки він не повинен писати за межі вихідного буфера. Обмеження коду унеможливлює написання одиничних байтів таким чином!
  • imul edx, [ecx+32], whatever- це головна скремблічна ідея. Маючи достатню кількість ентропії [ecx+32]та будь-яку кількість, вона може генерувати будь-які результати. Я використовую його для створення 2 або 3 байтів необхідних значень. Певне ускладнення полягає в тому, що, записуючи його на вихід, він повинен робити логічну роботу ORз тим, що вже є. Це іноді змушувало нуль пам'яті ще раз.
  • Для jmpповернення використовується варіант інструкції. Я вибрав це, тому що його кодування є 0xff, що відповідає нерозривному простору в кодовій сторінці 437. Трохи розтягнути правила, але в іншому випадку я думаю, що завдання неможливе ...

Збірник вихідного коду разом із програмою C, яка його запускає (використовує синтаксис Visual Studio):

#include <stdio.h>

__declspec(naked) void __fastcall doit(char* buf)
{
    __asm {
        push ' '
        pop eax

        dec ecx
        and [ecx+32], ah    // terminating 0 byte

        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah

        push 98
        pop edx
        or [ecx+32], edx
        imul dx, [ecx+32], 26183
        and [ecx+32], ah
        or [ecx+32], dx    // two bytes: [.']

        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        push 'sih '
        pop edx
        or [ecx+32], edx    // 4 bytes: [ his]

        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        push 538988610
        pop edx
        or [ecx+32], edx
        imul edx, [ecx+32], 544803081
        or [ecx+32], edx // 1 junk byte and 3 good bytes: (t's)

        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        push 'aht '
        pop edx
        or [ecx+32], edx    // 4 bytes: [ tha]

        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        push 'tuB '
        pop edx
        or [ecx+32], edx    // 1 junk byte and 3 good bytes: [But]

        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        push word ptr 8309
        pop dx
        or [ecx+32], dx
        imul edx, [ecx+32], 542312807
        or [ecx+32], edx    // 1 junk byte and 3 good bytes: [, ']

        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        push 'dias'
        pop edx
        or [ecx+32], edx    // 4 bytes: [said]

        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        push ' ehs'
        pop edx
        or [ecx+32], edx    // 4 bytes: [she ]

        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        push ' dnA'
        pop edx
        or [ecx+32], edx    // 4 bytes: [And ]

        push esp
        pop edx
        inc edx

        pop eax
        jmp dword ptr[edx-1]
    }
}

int main()
{
    char buf[100];
    doit(buf);
    puts(buf);
}

Здається, це не для мене повністю гольф. Звичайно, ви б зберегли кілька байтів за допомогою циклів, а не повторювали ряд однакових інструкцій. Все це dec ecx+ and [ecx+32], ahречі можна розглянути.
Коді Грей

Ви можете спробувати. Це найкраще, що я міг зробити; Я був би радий бачити інший підхід. Я вирішив відмовитись від ідеї циклів, коли побачив, що вони вимагають відхилення від негативного стрибка. Можливо, це обмеження можна вирішити творчо - я не знаю як.
anatolyg

1
@anatolyg Можливо, зводиться до позиції вашого тестового середовища щодо самовиправляючого коду. Або його думки щодо виконання коду, який ви створили на стеку.
гастропнер

Чи не 0xffпорушує знак "Ні пунктуації, ні алфавітні символи"?
val


13

PostScript, 889 874 837 835 байт

currentflat string dup rrand
count dup count count mul mul xor count count mul count dup mul exch count
count copy count copy count copy count copy count copy
add and sub put print
and sub add put print
sub sub add put print
mul or xor put print
idiv xor add put print
or xor add put print
mod idiv add put print
mul or xor put print
idiv xor add put print
sub and add put print
or and add put print
sub sub add put print
pop add sub put print
mul or xor dup copy put print
mod mul sub put print
add or xor put print
idiv add add put print
add or add put print
put print
add or add put print
or xor add put print
sub and add put print
add or add put print
mod mul sub put print
idiv xor add put print
mul or xor put print
or xor add put print
or and add put print
idiv xor add put print
xor add sub put print
mod mul sub put print
quit

Спробуйте в Інтернеті!

Для цього використовується 32 копії цілих чисел 89 25 20 6. Усі діаграми цільового рядка можна отримати за допомогою операцій над цими цілими числами в порядку стеку: наприклад, "A" (ASCII 65) - 89 - (25 & (20 + 6)). Багато 4-кортез цілих чисел мають цю властивість; цей вибір був обраний, оскільки їх особливо легко створити.

currentflat string dup rrand

Плоскі за замовчуванням до 1, тому це створює рядок довжиною 1 (ініціалізований до \0). dupне є глибокою копією: вона створює другу посилання на той самий рядок. rrand виштовхує випадкове насіння, яке за замовчуванням дорівнює 0. Стек зараз ["\0", "\0", 0].

count dup count count mul mul xor

count висуває кількість елементів у стеку, тому це обчислює 3 ^ (3 * (5 * 6)) = 89.

count count mul count dup mul exch count

4 * 5 = 20, 5 * 5 = 25, 6 = 6. Стек зараз ["\0", "\0", 0, 89, 25, 20, 6].

count copy count copy count copy count copy count copy

Дублюйте всю стеку, п’ять разів. Таким чином, ми закінчуємо 32 копії нашого початкового 7-елементного стека. Нам потрібно лише 31 копія, оскільки цільовий рядок становить 31 символ, але додаткова копія не зашкодить.

add and sub put print

Обчисліть шаркод з чотирьох перших цілих чисел, запишіть його в індексі 0 рядка, а потім надрукуйте рядок.

quit

Пригнічує запит за замовчуванням.


11

Рубі , 420 354 338 байт

def P a
print String a
end
def Q a
p String a
end
class String
def inspect
putc sum size
q
end
end
def w
Q def hacked
end
rescue
end
P def And
end
w
P def she
end
w
P def said
end
Q def gadget
end rescue
w
def a
Q def afraid
end
rescue
end
a
P def But
end
w
P def that
end
a
putc String def s
end
w
P def his
end
Q def fierce
end rescue
a

Спробуйте в Інтернеті!

У порядку зростання кудрявості:

Слова, що починаються з великої літери, можна роздрукувати, визначивши клас із цим іменем та зателефонувавши displayв тіло визначення класу.

Інші слова можна відобразити, визначивши методи з цим ім'ям, яке повертає символ, а потім перекидає його на рядок для видалення провідної двокрапки.

Інші символи можна відобразити, натиснувши putcїх ASCII код. Ми можемо генерувати відповідні числа, повторно використовуючи String defтрюк, щоб отримати рядок, потім взявши суму його байтів, використовуючи модуль, визначений його розміром. На жаль, у нас немає ніякого способу викликати методи на об'єкті, окрім як із класового визначення цього об’єкта, що ускладнює передачу аргументів. Таким чином, остаточний злом - це переосмислення String#inspect, яке викликається неявно при передачі String в pметод, так що він обчислює та видає відповідний символ як побічний ефект, перш ніж підвищувати помилку, щоб pфактично не вдалося закінчити виконання та надрукувати новий рядок Тоді нам потрібно врятувати помилку в основному коді.

Редагувати: Джордан зробив кількість байтів набагато менше, ах, високий, з деяким розумним керуванням потоком гольфу, і я вирізав ще кілька байтів, замінивши raiseоднобуквенний неіснуючий виклик методу, який викликає NameError.

Редагування 2: Помітив, що з print Stringвитягнутим методом дешевше просто використовувати це з визначенням методу, ніж використовувати трюк визначення класу, оскільки методам дозволено кесувати заголовок.


Красиво .... Я не розумію, як sum sizeсума модуля отримує свій розмір, але все інше перевіряється!
Значення чорнила

Я вважаю це трохи ліниво, він фактично передає розмір рядка як необов'язковий аргумент методу sum.
гістократ

11

> <> , 233 122 байти

cdacaabbglccgpcbfbbcaacdebbafbebbcebdbealbcpcdbcccdlcdpacbbalccpaalacpbcfafbaab









       g  sandBe
       o  Aviuth

Спробуйте в Інтернеті!

Це почалося як відповідь mbomb на гольф , але я виявив принциповий зсув, який економить величезну кількість байтів, тому я публікую це як свою власну відповідь.

Згенерування не алфавітних символів для виведення відбувається за допомогою багаторазового натискання значень на стек, потім за допомогою lнатискання на довжину стека. Однак, це не потрібно виводити негайно: використовуючи pцей символ, можна розмістити в будь-якій комірці, координати якої між 10 і 15 включно, щоб потім бути отриманим пізніше g. Аналогічно, алфавітні символи можна розмістити у вихідному вихідному коді та прочитати таким чином: оскільки найвищий не алфавітний код символів на вході становить 46 ( .), це означає, що стек не потрібно висувати вище, ніж 62, необхідні для зберігання всі 31 символи виводу.

Крім того, a vрозміщується в коді в стовпці 7. Коли вказівник інструкції обертається навколо і натискає це v, послідовність goвиконується повторно, щоб прочитати з висунутих координат і вивести відповідні символи. Врешті-решт, стек стає порожнім, а gпрограма закінчується помилкою.

Перші 7 байтів коду використовуються повторно, як і перші 7, так і останні 7 координат. Розміщення vв стовпці 9 теоретично зберегло б ще два байти, але змусило б символів Ainsvу квадрат 2х2 у коді, що неможливо. Більш рання версія використовувала стовпчик 15, але для цього потрібен додатковий рядок у вихідному коді і в кінцевому підсумку на шість байт довше.


Після подальшої думки я думаю, що я можу змусити роботу колонки 9, витративши байт на rпереміщення вирівнювання, куди хочу. Однак гольф цієї програми трохи зашкодить моєму мозку.
Нітродон

8

CJam , 262 байти

  KAbScibCmhc  CZbsic          GmQYbsic
S CmfYmeibc    ImqmeKmhcel     AZbAbc
S CmfYmeibc    KAbScibCmhcel   ImqmeKmhAmhcel  GmQYbsic    KAZbYbbBbc
S CGmQbDbc     EYbTYtZbc       FYbGmQbcel      EYbGmQbcel
S EYbGmQbcel   ImqmeKmhcel     KAbScibCmhcel   EYbGmQbcel  CGmQbDbc    CmfYmeibc
S ImqmeKmhcel  ImqmeKmhAmhcel  CmfYmeibc       PYmhmeKmhc  CGmQbDbc

Спробуйте в Інтернеті! Нові рядки тут показані лише для наочності; кожен рядок представляє символ.

Так, це було весело. Обмеження себе алфавітними командами викликає цікаві проблеми:

  • Без {і }практично немає можливості для управління потоком (за винятком того f, який я не знайшов можливості використовувати).
  • Без \, _, ;або $, у нас немає ніяких засобів для маніпулювання стека.

Це означає, що головна мета полягає в тому, щоб отримати відповідні кодові точки в стеку, а потім перетворити їх на символи c.

Проблема полягає в тому, що нам також бракує більшості основних арифметичних команд, а також цілих літералів. Це добре, оскільки mпростір імен містить численні вдосконалені математичні операції, і існує багато змінних, визначених корисними числами.

Я в кінцевому підсумку широко використовував квадратні корені ( mQі mq), експоненціальну функцію meта перетворення бази ( b), які також можна використовувати для емуляції множення ( [X 0] Ybобчислення X * Y). Крім того, іноді простіше побудувати кодову точку великого регістру, і в цьому випадку ми можемо використовувати el(перетворити в малі регістри) на отриманий символ.

Я все ще не задоволений деякими довшими. Ну добре.

Пояснення

Це пояснення результатів вибору символів за символом. Перш ніж почати, ось кілька коротких способів зробити цифри:

  • 0, 1, 2, 3, містяться в змінних T, X, Y, Zвідповідно.
  • Числа від 10 до 20 містяться в змінних Aнаскрізь K.
  • 32 можна зробити за допомогою Sci( Sвисуває рядок, що містить пробіл, cотримує перший символ цієї рядка та iперетворює цей символ у його кодову точку). Sтакож використовується для пробілів.
  • 4 задано GmQ(цілий квадратний корінь з 16).
  • 5 задається AZbYb(перетворити 10 в базу 3, поступившись [1 0 1]і перетворивши отриманий масив чисел у основу 2, отримавши 5).
  • 7 задається Ymei(обчислити exp (2) і перетворити в ціле число).

A

K           - push 20                        | 20
 Ab         - convert to base 10             | [2 0]
   Scib     - convert from base 32           | 64
       Cmh  - hypot(TOS, 12)                 | 65.115
          c - round down and convert to char | 'A

n

C      - push 12            | 12
 Zb    - convert to base 3  | [1 1 0]
   s   - convert to string  | "110"
    i  - convert to integer | 110
     c - convert to char    | 'n

d

GmQ      - push 4             | 4
   Yb    - convert to base 2  | [1 0 0]
     s   - convert to string  | "100"
      i  - convert to integer | 100
       c - convert to char    | 'd

s

C         - push 12         | 12
 mf       - factors         | [2 2 3]
   Ymeib  - base 7          | 115
        c - convert to char | 's

h

I           - push 18                        | 18
 mq         - sqrt                           | 4.242
   me       - exp                            | 69.591
     Kmh    - hypot(TOS, 20)                 | 72.408
        c   - round down and convert to char | 'H
         el - lowercase                      | 'h

e

A      - push 10              | 10
 Zb    - convert to base 3    | [1 0 1]
   Ab  - convert from base 10 | 101
     c - convert to char      | 'c

a

KAbScibCmhc   - push 'A (see above) | 'A
           el - lowercase           | 'a

i

I              - push 18         | 18
 mq            - square root     | 4.242
   me          - exp             | 69.591
     Kmh       - hypot(TOS, 20)  | 72.408
        Amh    - hypot(TOS, 10)  | 73.095
           c   - convert to char | 'I
            el - lowercase       | 'i

,

K          - push 20              | 20
 AZbYbb    - convert to base 5    | [4 0]
       Bb  - convert from base 11 | 44
         c - convert to char      | ',

'

C        - push 12              | 12
 GmQb    - convert to base 4    | [3 0]
     Db  - convert from base 13 | 39
       c - convert to char      | ''

B

E         - push 14               | 14
 Yb       - convert to base 2     | [1 1 1 0]
   TYt    - replace elem 0 with 2 | [2 1 1 0]
      Zb  - convert from base 3   | 66
        c - convert to char       | 'B

u

F          - push 15             | 15
 Yb        - convert to base 2   | [1 1 1 1]
   GmQb    - convert from base 4 | 85
       c   - convert to char     | 'U
        el - lowercase           | 'u

t

E          - push 14             | 14
 Yb        - convert to base 2   | [1 1 1 0]
   GmQb    - convert from base 4 | 85
       c   - convert to char     | 'T
        el - lowercase           | 't

.

P          - push pi                        | 3.141
 Ymh       - hypot(TOS, 2)                  | 3.724
    me     - exp                            | 41.437
      Kmh  - hypot(TOS, 20)                 | 46.011
         c - round down and convert to char | '.

1
Ви можете здійснювати конверсії бази з цифрами поза межами звичайного діапазону, наприклад HYbYCtYbc, HYbXAtYbcта HYbXBtYbc.
Нітродон

7

Мертвий риб ~ , 943 байт

iiisdsiciiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiicddddddddddcddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcdddddddddddddddddddddsddddddcdddddddddddcdddcdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcdddddddddddddddddddddsddddddcddddddddddddddddddciiiiiiiicdddddcddddddddddddddddddddddddddddddddddddddddddddddddddddddddcddddddddddddciiiiiiiciiiiiiiiiiiiiiiiiiiiiiiiiiiciiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiicdcddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcdddddddddddddddddddddsdddddcddddddddddddcdddddddciiiiiiiiiiiiiiiiiiicdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcddddddddddddddddddddddddddddsddddddcdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcddddddddddddddddddddddsiiiiciciiiiiiiiiicdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcdddddddc

Спробуйте в Інтернеті!

Не допускається циклів :(




6

MATL , 187 158 байт

IEWQKEtqhpEqqKQHhthpKWEyQKWEqqYqQQXJwtQQQwKWEJKQthpYqKQHhthptQQQQQwIIhKQhpqKWEIWKQhpqIEWQQJQQtqKWEyIIhIhpYqQXJyKQthpYqwIWKQhpqyqKWEyJtQwhhPIIhKQhpQIWKQhpqvlec

Спробуйте в Інтернеті!

Більш прочитана версія: Спробуйте його в Інтернеті! Ручна спроба побудови рядка. Напевно, є багато місця для гольфу, розрізавши струну на зручні шматки, використовуючи Pта hперевертаючи та будуючи струну. Я сподіваюся, що хтось візьметься за виклик, щоб перевершити мене. Основна проблема полягає в тому, що ви не можете використовувати +або -, таким чином, основна арифметика часто неможлива.

Основні моменти:

  • KQthpYq: 25-й ( KQthp) прайм Yq- 97, що відповідає букві a. Буква s(115) формується аналогічно від 113, 30-го простого числа. Потім він широко використовується в буфері обміну J.
  • hisскорочується, зберігаючи hз раніше в буфер обміну J. Оскільки це було раніше збережене s, ми будуємо hisв зворотному порядку, щоб ми все-таки змогли отримати останнє sвикористання yта перевернути його після використання P.
  • Велика кількість байтів збережена завдяки Луїсу Мендо (в основному, змінивши купу hна vle)

Ага - я дійсно думав, що використання vбуде возитися з тим, hщо було раніше. Здогадайтесь, я мав би це зробити, а не просто припускати. Крім того, спасибі за голову, відбулося надмірне видалення. Мені цікаво побачити, чи зможете ви зробити краще, ніж це ...
Санчіз

Я хотів би спробувати, але доведеться почекати. Відповідь на це, здається, займає багато часу!
Луїс Мендо

1
@LuisMendo Yup. Для того, щоб зробити це, у мене пішла година, або це стосується лише локальної оптимізації. Я впевнений, що можна краще зробити трохи більше глобального погляду на речі.
Санчіз

Моя спроба . Я не дивився на ваші, тому сподіваємось, що підходи сподіваються різні
Луїс Мендо

@LuisMendo Я повністю забув це Uозначає ^2, що міг би врятувати мене небагато байтів ...
Sanchises

6

MATL , 118 байт

KEUQtVQsQKBFZAXHKUqyyhsXJyyhdQtQQQwOJIUEyhdtKEhsHKQYqEEKQyywhdXJKEUQQHKUhstQwOytHKhsKYqyhdbJyqOHKhstQHKUqhsKUqYqqJvlec

Спробуйте в Інтернеті!

Більш прочитана версія (кожен рядок відповідає одному символу, за винятком операцій з перестановки стеків).

Пояснення

Програма виробляє кодові точки необхідних символів, як незалежні номери. Наприкінці всі ці числа об'єднуються у вектор стовпця, перетворюються у векторний рядок та перетворюються на символи. Результат неявно відображається.

Деякі з використаних хитрощів:

  • Більшість кодових точок нижче 32 відображаються як пробіл. Так 0використовується для більшості просторів, оскільки коштує лише байт ( O).
  • Однак для першого простору 15використовується (згенеровано як KUq), оскільки він може бути використаний повторно, додавши його в 100(char d), щоб give 115( s). В іншому випадку 5використовується для простору (згенеровано як KQ), тому його можна пізніше відняти від 44( ,), щоб дати 39( ').
  • Буфер обміну Jвикористовується для зберігання символів, які будуть повторюватися: спочатку s, потім '. Так само Hзберігається буфер обміну 100, що корисно dі для генерування інших персонажів.
  • Широке використання функцій Q(додавання 1), q(віднімання 1), E(множення на 2) та U(квадрат) разом із заздалегідь заданими буквами в буферах обміну I( 3) та K( 4).
  • Довільне додавання та віднімання здійснюється шляхом об'єднання у вектор ( h) та обчислення його суми ( s) або послідовних різниць ( d).
  • 100( d) генерується, як 4у двійковій інтерпретації, як десяткове число.
  • 110( n) отримується з 65( A) шляхом перетворення в рядок ( '65': кодові точки [54 53]), додавання 1до кодових точок ( [55 54]), підсумовування їх разом та додавання 1.
  • Порядок генерації чисел іноді змінюється для зручності; і вони перепорядковуються функціями перестановки стека: swap ( w), bubble up b).

1
Дуже хороша! Розумний дотик, використовуючи Oзамість KWEпробілів. І ти підтвердив мою підозру, що, мабуть, краще пожертвувати іншим буфером обміну H.
Санчіз

5

постійного струму , 240 222 209 байт

OOOOOziOOOOOOOOOOOOOOOOOOOOOOOOOOOzddddddzkdddzasBdzasAdzscdzdasCzsdOOlAxlAxPOBlBxdIlAxoPAdlBxddsrIlAxssPPOPlsIZlCxddspPOZlCxPPOPlrdZlCxPlsPlrPlcPPKPdZlBxdZlAxPOAZlAxdPIZlCxdPrPdPlpPlrdZlCxPPKPOPPlpPlsPOPldPKP

Спробуйте в Інтернеті!

Моя перша думка була такою ж, як @seshoumara, просто натисніть достатню кількість матеріалів на стек, щоб генерувати значення ASCII усіх символів. Тоді мені прийшло в голову, що оскільки +, -і *є односимвольними операторами, я можу їх просто відтворити і мати можливість використовувати арифметику! Звичайно, це було б менше! І я не був би здивований, якщо мені вдасться відіграти більше байтів, але поки що ... цей спільний підхід зумів зв’язати наївний (іш).

OOOOOziOOOOOOOOOOOOOOOOOOOOOOOOOOOzddddddzkdddzasBdzasAdzscdzdasCzsdце частина підходу, схожа на @ seshoumara's, але ми піднімаємось лише до 46, що є .. Ми робимо це тому, що нам потрібно подорожувати до 45, -а також нам потрібен період у нашому рядку, тому просто йти далі далі за період (я думаю) найдешевше. По дорозі ми зберігаємо деякі значення: 5, 32, 39 всі згодом знадобляться. 5 - для утилітарних речей, 32 та 39 - для їх значень ASCII. Спочатку я робив 1-5, але це було дорого, і я міг просто уникати використання 4; використовувати Z(вивести значення, натиснути кількість цифр, яке воно має) на три-, дво- або одноцифрове число для цих значень. На 42, 43 і 45, ми перетворюємо їх в рядки ( *, +і -відповідно) і зберігати їх в вигляді макросів ( B, AіCвідповідно). Це означає, що без використання символів *+-ми можемо використовувати ці оператори.

Звідси ми, в основному, починаємо генерувати значення ASCII, використовуючи математичну силу замість простого накопичення, зберігаючи частину повторів по ходу. 100, 105 та 115 придумали достатньо, щоб зберігання їх (у регістрах чи іншим чином) мало сенс. Спочатку я залишив стопку, заповнену 10, і використав їх для створення 100; в кінцевому підсумку збереження байтів заповнило стек 32 і використовувати їх як пробіли пізніше. Трохи більше читається версія розділу ASCII: OOlAxlAxP OBlBxdIlAxoP AdlBxddsrIlAxssP P OP lsIZlCxddspP OZlCxP P OP lrdZlCxP lsP lrP lcP P KP dZlBxdZlAxP OAZlAxdP IZlCxdP rPdP lpP lrdZlCxP P KP OP P lpP lsP OP ldP KP.

Поголив 18 байт шляхом: збереження числа 5 як вхідного радіуса замість регістра; число 32 як точність замість регістру; число 115 як вихідний радіус замість регістра; то довелося змінити , KZщоб IZгенерувати 1s і OZдля KZгенерувати 2s.

Поголив ще 13 байт, затопивши стек 32s; встановлення точності до 39; використання маніпуляцій стеком, щоб уникнути зберігання 116; вирізавши якусь подвійну роботу, яку я випадково залишив.


+1 Хороша ідея використовувати aдля відтворення цих операторів, а потім для виклику їх x. Це показує поведінку dc-коду постійного струму. Коли я встигну, я застосую ваш останній трюк зберігання даних у параметри замість регістрів. Як ви думаєте, ми могли б отримати ще коротше рішення постійного струму, зловживаючи способом роботи P, щоб надрукувати більше листів за один раз, якщо нам пощастить ввести необхідну величезну кількість лише за допомогою шістнадцяткових знаків?
seshoumara

@seshoumara Це можливо, хоча мої спроби зробити це з іншими викликами свідчать, що це малоймовірно просто тому, що ці значення швидко стають великими. Просто для отримання перших двох букв "An" нам потрібно P16750 або 0x416E. Якщо нам просто пощастило, і одна з підрядів складалася виключно зі значень AF, то це може отримати нам ярлик. Це було б трохи удачі, хоча! В іншому випадку ми або хоч якось вводимо велику кількість, придумуємо їх якось, або робимо багато додавання і множення на 256. Що здається ... кумеднішим, ніж купу Ps.
brhfl

5

Japt , 87 байт

Bs g caA
HzG
Ts caV
iWisiiihiSisiUitiaihitiSitiuibu iUiSiWcaV idiiiaisiSieihisiSidiniau

Спробуй це

Пояснення

Перший рядок генерує 'та присвоює йому змінну U.

Bs g caA
B                            :11
 s                           :To string
   g                         :First character
     c                       :Character code
      a                      :  Absolute difference with
       A                     :  10

Другий рядок призначається 2змінній V.

HzG
H                            :32
 z                           :Floor divided by
  G                          :16

Третій рядок генерує .та присвоює йому змінну W.

Ts caV
Ts                           :Convert 0 to a string
   caV                       :Absolute difference of its charcode with V (2)

Останній рядок, таким чином, будує рядок один символ одночасно у зворотному напрямку.

iW...ibu ...iWcaV ...iau
iW                           :Start by prepending W (.) to U (')
  ...                        :Each i prepends the literal character that follows it to the string, with S being space and U being "'"
     ibu                     :As B is the constant for 11 and it can't be quoted, here i prepends "b" to the string and u uppercases it
         ...                 :As above, each i is prepending the character/constant that follows it to the string
            iWcaV            :Gets the absolute difference of the charcode of W (.) and V (2) to get the "," and prepends that
                  ...        :Some more literals
                     iau     :And, finally, the same trick is used for the "A" as was for the "B", as A is the constant for 10

Приємне рішення. Можна зберегти байт, замінивши перший рядок наQc dGaB
Втілення ігнорування

4

Червоний , 272 байти

prin quote And prin sp prin quote she prin sp prin quote said prin comma prin sp prin subtract to sp mold quote G sp prin quote But prin sp prin quote that prin subtract to sp mold quote G sp prin quote s prin sp prin quote his prin dot prin subtract to sp mold quote G sp

Якщо потрібні подвійні лапки:

Червоний , 344 байти

prin subtract to sp mold quote B sp prin quote And prin sp prin quote she prin sp prin quote said prin comma prin sp prin subtract to sp mold quote G sp prin quote But prin sp prin quote that prin subtract to sp mold quote G sp prin quote s prin sp prin quote his prin dot prin subtract to sp mold quote G sp prin subtract to sp mold quote B sp

Не працює в TIO, але працює в червоному перекладачі.

Червона консоль

Пояснення:

Слова тривіальні - я друкую їх (друкуйте без нового рядка) як букви quote. У червоному є вбудоване слово для простору - sp, як і commaі dot. "і 'ще цікавіше: я друкую їх, віднімаючи пробіл від Bі, Gвідповідно, починаючи з буквального Bі Gперетворюючи їх спочатку в рядок з, moldа потім в символ (щоб використовувати на них віднімання) wtih to sp( Red має перетворення за прототипом - конвертувати рядок до типу sp, який є символом).


1
Питання було уточнено; вони зняли з неї цікаву частину.
anatolyg

@anatolyg Спасибі, мені це потрібно для цього ', тому рішення з 272 байтом таке саме.
Гален Іванов

4

Четверта (gforth), 351

CHAR A DUP EMIT
CHAR n EMIT
CHAR d EMIT
SPACE
CHAR s DUP EMIT
CHAR h EMIT
CHAR e EMIT
SPACE
EMIT
CHAR a EMIT
CHAR i EMIT
CHAR d EMIT
DUP CHAR m XOR EMIT
SPACE
CHAR f XOR DUP EMIT
CHAR B EMIT
CHAR u EMIT
CHAR t DUP EMIT
SPACE
DUP EMIT
CHAR h EMIT
CHAR a EMIT
EMIT
DUP EMIT
CHAR s EMIT
SPACE
CHAR h EMIT
CHAR i DUP EMIT
CHAR s EMIT
CHAR G XOR EMIT
EMIT

Шкода , я не можу перевизначити CHAR або EMIT на один-буквених слів, так як це вимагає використання або :і ;(наприклад : C CHAR ;) або '(наприклад ' CHAR ALIAS C)

Насправді, якби я міг визначити слова, я міг би зробити, : P CHAR EMIT ;а потім зробити P xдрук x. Ну добре.

Я навіть не можу створити буфер, записати туди цю послідовність знаків, а потім використовувати це як вхід, оскільки для запису в пам'ять потрібно використовувати !абоC!



3

Пепе , 266 байт

Я тримаю стек r порожнім, а 's' на стеку R

reeEeeeeeE reeEEeEEEe reeEEeeEee reEe REeEEEeeEE Reee reeEEeEeee reeEEeeEeE reEe Reee reeEEeeeeE reeEEeEeeE reeEEeeEee reeeEeEEee reEe reeeEeeeEe reeEeeeeEe reeEEEeEeE reeEEEeEee reEe reeEEEeEee reeEEeEeee reeEEeeeeE reeEEEeEee reeeEeeEEE Reee reEe reeEEeEeee reeEEeEeeE Reee reeeEeEEEe reeeEeeeEe

Це не в TIO, але ви можете спробувати тут


3

постійного струму , 240 байт

Основна ідея полягає в постійному зростанні стека на 1 ( K), зберігаючи ( sX) розмір стека ( z) в користувацькі регістри, коли він відповідає кожному унікальному коду ASCII. Друк ( P) виконується на всьому протязі.

KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKzsSKKzsQKKKKKzsqKKKKKzsCKKzsDKKKKKKKKKKKKKKKKKKKzPKzsBKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKzsaKKKzsdKzseKKKzshKzsiKKKKKzPldPlSPKKKKKzsszPlhPlePlSPlsPlaPliPldPlCPlSPlqPlBPKzdstzPdPlSPdPlhPlaPPlqPlsdPlSPlhPliPPlDPlqP

Спробуйте в Інтернеті!

Я зробив деяку оптимізацію, як, наприклад, не зберегти літеру, якщо він не використовується після цього, як дублювання ( d) літери, наприклад, t, у стеці, щоб зберегти байт, оскільки call ( lX) - 2 байти.


Я придумав рішення постійного струму, яке використовує арифметику, створюючи макроси для +, - і *. Це 262 байти. Я буду намагатися оптимізувати це, щоб спробувати вийти конкурентоспроможним, але мушу сказати, що я розчарований, що це набагато жирніше, ніж (відносно) наївне рішення.
brhfl

@brhfl Так, DC дуже швидко отримує багатослівний вислів. Навіть так, я дуже хотів би побачити ваше рішення, тому опублікуйте це! Тим часом я також замислююся над тим, щоб більше пограти в поточний метод, використовувати програму, або придумати іншу ідею для постійного струму.
seshoumara

Мені вдалося зв'язати 240! І я не був би здивований, якби мені вдалося відіграти ще один або два байти, але ... це набагато більш тупий підхід за невеликим / без виграшу. У всякому разі, я розмістив його там десь ...
brhfl

Я прийшов до 222, замінивши кілька моїх найпоширеніших регістрів w / input / output radix та точність; економить один байт у магазині та один байт на кожному завантаженні ... Оскільки цифри несуттєві, це нічого не впливає ... Можливо, ви також зможете використовувати це на вашу користь!
brhfl

3

Машинний код 80186+, формат MS-DOS .COM, 822 787 байт

Крім букв, використовуються лише вкладки та пробіли. Зважаючи на те, що більшість опкодів у дозволеному діапазоні є певними кроками, декрементами, натисканнями, спливаючими елементами, а також непрямими і ІР-OR-опорами, крім IMUL, я використовую той факт, що реєстр стеків обгортається, коли він потрапляє в кінець сегмента для зміни коду в зворотному порядку! Необхідна збірка 80186+, оскільки я натискаю на негайні значення.

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXjhX   GXkOXYIQSX GXjdX    GXkOXwIIIIIIIIIQhhihs kOXeQh ihutSXH    GXHHHHHH GXSX GYkOXDAAAQSX GXjGX    GXkOXtQhidhsahe hshhd hAnSX GXjTX   GXkOXdIIIQkOXgAQSX GXHHHHHHHHHHHHHHHHHHHHH  GXSX GYkOXbAAAAAAAAAAAAAAQhhlh  Xhh qM

Анотоване джерело (формат TASM):

IDEAL
P186

MODEL   TINY
CODESEG
ORG 100H

MAIN:   
REPT 582
    POP AX  ; Set up stack to end of string
ENDM

    PUSH 68H
    POP AX
    OR [BX+58H],AX
    IMUL CX,[BX+58H],59H ; 68H*59H=2428H
    DEC CX ; -1=2427H
    PUSH CX

    PUSH BX
    POP AX
    AND [BX+58H],AL
    PUSH 64H
    POP AX
    OR [BX+58H],AX
    IMUL CX,[BX+58H],77H ; 64H*77H=2E7CH
REPT 9
    DEC CX ; -9=2E73H
ENDM
    PUSH CX

    PUSH 6968H
    PUSH 2073H

    IMUL CX,[BX+58H],65H ; 64H*65H=2774H
    PUSH CX

    PUSH 6920H
    PUSH 7475H

    PUSH BX
    POP AX
    DEC AX
    OR [BX+58H],AX ; FFFFH
REPT 6
    DEC AX
ENDM
    AND [BX+58H],AL ; FFF9H
    PUSH BX
    POP AX
    AND [BX+59H],AL ; 00F9H
    IMUL CX,[BX+58H],44H ; 0F9H*44H=4224H
REPT 3
    INC CX ; +3=4227H
ENDM
    PUSH CX

    PUSH BX
    POP AX
    AND [BX+58H],AL
    PUSH 47H
    POP AX
    OR [BX+58H],AX
    IMUL CX,[BX+58H],74H ; 47H*74H=202CH
    PUSH CX

    PUSH 6469H
    PUSH 6173H
    PUSH 2065H
    PUSH 6873H
    PUSH 2064H
    PUSH 6E41H

;; CODE STARTS:
;; PUSH 0909H
;; POP AX
;; PUSH 046CH
;; POP DX
;; INT 21H
;; INT 20H

    PUSH BX
    POP AX
    AND [BX+58H],AL
    PUSH 54H
    POP AX
    OR [BX+58H],AX
    IMUL CX,[BX+58H],64H ; 54H*64H=20D0H
REPT 3
    DEC CX ; -3=20CDH
ENDM
    PUSH CX

    IMUL CX,[BX+58H],67H ; 54H*67H=21CCH
    INC CX ; 21CDH
    PUSH CX

    PUSH BX
    POP AX
    AND [BX+58H],AL
REPT 21
    DEC AX
ENDM
    OR [BX+58H],AX ; 0FFEBH
    PUSH BX
    POP AX
    AND [BX+59H],AL ; 0EBH
    IMUL CX,[BX+58H],62H ; 0EBH*62H=59F6H
REPT 14
    INC CX ; +14=5A04H
ENDM
    PUSH CX

    PUSH 6C68H
    PUSH 5809H
    PUSH 0968H

    JNO $+4FH

END MAIN
ENDS

Це не збірка, це машинний код ...
Artelius

@Artelius Ярмарок досить. Я оновив опис.
ErikF

3

Befunge-98 (FBBI) , 125 124 121 байт

wab









And she said   But that s his












wakekekaayyeapwayyaayybyapayybyapcyabcyaayycayyba
a



b
wayapapoq

Спробуйте в Інтернеті! Виводить файл з назвою \n(єдиний новий рядок). Дякую Джо Кінгу за його сценарій.

Результат включає 10 останніх нових рядків.

Для одного лише останнього рядка +1 байт , змінивши наступний рядок:

wakekekaayyeapwayydayybyapayybyapycyabcyaayycayyba

Спробуйте в Інтернеті!


Пояснення:

Вказівник переміщується таким чином:IP-шлях

Програма ставить не алфавітні символи, перш ніж виводити цей рядок у файл.

Befunge-98 включає в себе інструкції a... f, які висувають відповідне шістнадцяткове значення до стеку. Для генерації інших чисел він передає ці значення y("Отримати SysInfo") як аргументи для отримання:

10  y-position
11  x-position
12  y-velocity (= 0)
13  x-velocity (= 1)

23* stack size

Розміщуючи основну частину коду у y = 23, ayyможна використовувати для повторного доступу до розміру стека, який потім використовується для генерації символьних кодів.


Чи не дозволений лише один зворотний ряд?
Delioth

У публікації зазначено, що "Пробіл повністю дозволений". Я думаю, що це круто зловживати цим формулюванням, щоб виправдати сліди нових рядків!
anatolyg

2

Pyth , 210 байт

pChyCdpCyhyhlGpCyytlGpdpChFhTyylGpCyylGpChyytlGpdpChFhTyylGpCtytytlGpChyylGpCyytlGpCyyhTpdpCtyyTpCyhCdpCtFyyCdhTpCyhFlGCdpdpCyhFlGCdpCyylGpCtytytlGpCyhFlGCdpCtyyTpChFhTyylGpdpCyylGpChyylGpChFhTyylGpCyhyhTpCtyyT

Спробуйте в Інтернеті!

Я знайшов кілька цифр, які можна виразити лише за допомогою літер (наприклад, T10, Z= 0, lG= довжина (алфавіт) = 26, Cd= charcode (пробіл) = 32), і кілька функцій, які можна виконати, використовуючи лише літери (наприклад, t= декремент, h= приріст, hF= повторне застосування прирощення = додавання), а потім просто запустив грубу силу пошуку, щоб знайти найкоротші комбінації тих функцій і чисел, які призвели до кожної з потрібних мені літер.


2

16-бітний код складання x86, 665 байт

(двійковий файл буквений, а не джерело)

Я якось забув про правило, що дозволяє пробіл. Безумовно, в результаті код може бути переграний.

Байт-код:

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXsBFVKZPFFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXkLAFQQZJJJRkDCGPLXDPDJRkDBEPZJJRLZDRDZAAAQPLYDQDYXXDQhishZhDRDhZsDQDhaththRDhuthZBDQDRhidhsaRDhhehZsDRDhndhZADTZPiDEFY

Джерело:

    db    63 dup (58h) ;pop ax
    jnb   label1
    dw    5646h      ;magic #1
    dw    5a4bh      ;magic #2
    dw    4650h      ;magic #3
    dw    (42h-6)/2 dup ("PF")

label1:
    db    416 dup (58h) ;more pop ax
    imul  cx,[si+41h],46h ;cl=24h (string sentinel)
    push  cx         ;push string sentinel
    push  cx
    pop   dx         ;dl=24h
    dec   dx
    dec   dx
    dec   dx         ;dl=21h
    push  dx         ;save for later
    imul  ax,[si+43h],47h ;al=0CDh
    push  ax         ;push xxCDh
    dec   sp         ;insert xx
    pop   ax         ;ah=0CDh
    inc   sp         ;discard xx
    push  ax         ;push 0CDxx
    inc   sp         ;discard xx
    dec   dx         ;cl=20h (space)
    push  dx
    imul  ax,[si+42h],45h ;al=2Eh (dot)
    push  ax
    pop   dx         ;dl=2Eh
    dec   dx
    dec   dx         ;dl=2Ch (comma)
    push  dx         ;push xx2Ch
    dec   sp         ;insert xx
    pop   dx         ;dl=2Ch
    inc   sp         ;discard xx
    push  dx         ;push 2Cxxh
    inc   sp         ;discard xx
    pop   dx         ;dx=202Ch
    inc   cx
    inc   cx
    inc   cx         ;cl=27h (quote)
    push  cx         ;push xx27h
    push  ax         ;push xx2Eh
    dec   sp         ;insert xx
    pop   cx         ;ch=2Eh
    inc   sp         ;discard xx
    push  cx         ;push 2Exxh
    inc   sp         ;discard xx
    pop   cx         ;cx=272Eh
    pop   ax         ;discard xxxx
    pop   ax         ;ax=0CD21h
    inc   sp         ;discard xx
    push  cx         ;push ".'"
    push  7369h      ;push "is"
    push  685ah      ;push "h"+xx
    inc   sp         ;discard xx
    push  dx         ;" "+xx
    inc   sp         ;discard xx
    push  735ah      ;push "s"+xx
    inc   sp         ;discard xx
    push  cx         ;push "'"+xx
    inc   sp         ;discard xx
    push  7461h      ;push "at"
    push  6874h      ;push "th"
    push  dx         ;push " "+xx
    inc   sp         ;discard xx
    push  7475h      ;push "ut"
    push  425ah      ;push "B"+xx
    inc   sp         ;discard xx
    push  cx         ;push "'"+xx
    inc   sp         ;discard xx
    push  dx         ;push ", "+xx
    push  6469h      ;push "id"
    push  6173h      ;push "sa"
    push  dx         ;push " "+xx
    inc   sp         ;discard xx
    push  6568h      ;push "he"
    push  735ah      ;push "s"+xx
    inc   sp         ;discard xx
    push  dx         ;push " "+xx
    inc   sp         ;discard xx
    push  646eh      ;push "nd"
    push  415ah      ;push "A"+xx
    inc   sp         ;discard xx
    push  sp
    pop   dx         ;dx=sp
    push  ax
    imul  ax,[si+45h],5946h ;ah=09h

Це працює так:

  • переміщує покажчик стека до кінця коду через POP AX (не можна POP SP, оскільки це не за алфавітом);

  • будує інструкцію щодо відправлення виклику DOS (алгоритмічно, оскільки це не за алфавітом);

  • будує неабетичні символи;

  • розміщує рядок на стеці;

  • розміщує інструкцію диспетчеризації в стеці в точному кінці коду, так що виконання тече безпосередньо до цієї інструкції;

  • будує інструкцію надрукувати рядок;

  • відображає рядок, і вони негайно виходять з ладу. : - / (Для витонченого виходу потрібно більше коду)




0

80186 код машини + DOS, 91 байт

Текстова версія:

hm  j   j   PPjzjzjgaAAA    JSJJ    RU  Sq  ReAA    JdJJJ   RfiJElK JEiS GtI And she said   But that s his   

Текстова версія, вкладки (код 9) замінена на 9пробіли, а пробіли (код 32) замінені на *:

hm9j9j9PPjzjzjgaAAA9JSJJ9RU9Sq9ReAA9JdJJJ9RfiJElK9JEiS*GtI*And*she*said***But*that*s*his***

Hexdump:

68 6D 09 6A 09 6A 09 50 50 6A 7A 6A 7A 6A 67 61
41 41 41 09 4A 53 4A 4A 09 52 55 09 53 71 09 52
65 41 41 09 4A 64 4A 4A 4A 09 52 66 69 4A 45 6C
4B 09 4A 45 69 53 20 47 74 49 20 41 6E 64 20 73
68 65 20 73 61 69 64 20 20 20 42 75 74 20 74 68
61 74 20 73 20 68 69 73 20 20 20

Машинний код з'являється у файлі з розширенням .com. Коли я запускаю його, він роздруковує потрібне повідомлення, а потім висить (виконує випадкові дані).

Пояснення на високому рівні про те, що це робить:

  1. Ініціалізує регістри з постійними значеннями
  2. Заміщує пробіли в повідомленні необхідними спеціальними символами ( ,'.$)
  3. Виправляє код для створення int 21інструкції, яка друкує повідомлення
  4. Дзвінки DOS

Код складання (можна скласти з tasm):

my_bp equ 7ah
my_si equ 7ah
my_di equ 67h
my_msg equ 13bh
    .model tiny
    .code
    .startup
    .186
    org 100h
    push 96dh   ; ax (ah = 0; al = don't care, but see below)
    push 9      ; cx
    push 9      ; dx
    push ax     ; bx = don't care
    push ax     ; don't care
    push my_bp
    push my_si
    push my_di
    popa
    inc cx
    inc cx
    inc cx
    or [bp+si+my_msg-my_bp-my_si+12], cx ; ,
    dec dx
    dec dx
    or [bp+si+my_msg-my_bp-my_si+14], dx ; '
    or [bp+di+my_msg-my_bp-my_di+23], dx ; '
    or [bp+si+my_msg-my_bp-my_si+30], dx ; '
    inc cx
    inc cx
    or [bp+si+my_msg-my_bp-my_si+29], cx ; .
    dec dx
    dec dx
    dec dx
    or [bp+si+my_msg-my_bp-my_si+31], dx ; $

    ; 0x2049 * 0x4b6c = 0x98301cc
    ; So this sets cx to 1cc (a temporary constant used to patch code)
    imul cx, [bp+si+my_msg-my_bp-my_si-2], 4b6ch
    ; 0x1cc | 0x2049 = 0x21cd (the instruction which calls DOS int 21)
    ; Here ah = 9 ("print" mode)
    or [bp+si+my_msg-my_bp-my_si-2], cx

    ; At address 101, there is the constant 96d, which was loaded into ax
    ; 0x96d * 0x7447 = 0x448013b
    ; So the following sets dx to 13b (adddress of the message)
    imul dx, [bp+di+101h-my_bp-my_di], 7447h

int21:
    dw 2049h

    db 'And she said   But that s his   '
    end

Він використовує popaінструкцію для появи всіх регістрів, тому що регулярний popне може заповнити всі необхідні регістри (наприклад pop di, заборонений код).

Адреси байтів для виправлення знаходяться в діапазоні 0x100 ... 0x160. На щастя, їх можна представити у вигляді суми в 3 байти з дозволеними значеннями:

  • 0x7a в bp
  • 0x7a або 0x67 в siабоdi
  • Негайне значення

Патчінг байтів у повідомленні працює, здійснюючи логічне значення OR0x20 (пробіл) та малу константу (4, 7, 12 або 14). Мала константа виходить шляхом ініціалізації cxта dxдо 9 (символ табуляції) та виконуючи INCабо DECза потреби

Для виправлення коду використовується IMULінструкція. Я знайшов потрібні 16-бітові константи для множення, використовуючи грубу силу пошуку.

Нарешті, адреса повідомлення (0x13b) отримується шляхом множення. Для економії місця я взяв одну з констант з однієї з інструкцій, яка містить негайне значення 0x96d. Тут 9частина вибирає функцію друку DOS, а 6dчастина - вільний параметр. Виявляється, 6dце єдина можливість, яка може дати 0x13b після множення.

Розбирання кодової частини:

06BA:0100 686D09            PUSH    096D
06BA:0103 6A09              PUSH    +09
06BA:0105 6A09              PUSH    +09
06BA:0107 50                PUSH    AX
06BA:0108 50                PUSH    AX
06BA:0109 6A7A              PUSH    +7A
06BA:010B 6A7A              PUSH    +7A
06BA:010D 6A67              PUSH    +67
06BA:010F 61                POPA
06BA:0110 41                INC     CX
06BA:0111 41                INC     CX
06BA:0112 41                INC     CX
06BA:0113 094A53            OR      [BP+SI+53],CX
06BA:0116 4A                DEC     DX
06BA:0117 4A                DEC     DX
06BA:0118 095255            OR      [BP+SI+55],DX
06BA:011B 095371            OR      [BP+DI+71],DX
06BA:011E 095265            OR      [BP+SI+65],DX
06BA:0121 41                INC     CX
06BA:0122 41                INC     CX
06BA:0123 094A64            OR      [BP+SI+64],CX
06BA:0126 4A                DEC     DX
06BA:0127 4A                DEC     DX
06BA:0128 4A                DEC     DX
06BA:0129 095266            OR      [BP+SI+66],DX
06BA:012C 694A456C4B        IMUL    CX,[BP+SI+45],4B6C
06BA:0131 094A45            OR      [BP+SI+45],CX
06BA:0134 6953204774        IMUL    DX,[BP+DI+20],7447
06BA:0139 CD21              INT     21 (after the code patches itself)

Факт забави: Зазвичай я використовував би offset messageзамість жорсткого кодування 13bh, але в цьому випадку, оскільки під час розбору його адреси невідомо, тасм генерує 16-бітове негайне зміщення, витрачаючи 1 байт коду:

06BA:0131 098A4600          OR      [BP+SI+0046],CX
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.