概要
paiza.ioでelixirやってみた。
練習問題やってみた。
練習問題
俺cpuのアセンブラから、x64アセンブラを生成し、コンパイル、実行せよ。
fizzbuzzを実行せよ。
サンプルコード
defmodule Top do
use Agent
def start_link() do
Agent.start_link(fn ->
0
end, name: __MODULE__)
end
def get() do
Agent.get(__MODULE__, fn v ->
#IO.puts v
v
end)
end
def set() do
Agent.update(__MODULE__, fn v ->
0
end)
end
def push() do
Agent.update(__MODULE__, fn v ->
v + 1
end)
end
def pop() do
Agent.update(__MODULE__, fn v ->
v - 1
end)
end
end
defmodule Asm do
def start_link do
Agent.start_link(fn ->
%{u: ""}
end, name: __MODULE__)
end
def push(a) do
Agent.update(__MODULE__, fn v ->
cond do
Top.get == 0 ->
str = " mov $#{a}, %r11\n"
%{v | u: v.u <> str}
Top.get == 1 ->
str = " mov $#{a}, %r12\n"
%{v | u: v.u <> str}
true ->
str = " push?\n"
%{v | u: v.u <> str}
end
end)
Top.push
end
def set(a) do
Agent.update(__MODULE__, fn v ->
cond do
Top.get == 0 && a == "a" ->
str = " mov %r12, %r13\n"
%{v | u: v.u <> str}
Top.get == 0 && a == "b" ->
str = " mov %r12, %r14\n"
%{v | u: v.u <> str}
Top.get == 0 && a == "c" ->
str = " mov %r12, %r15\n"
%{v | u: v.u <> str}
Top.get == 1 && a == "a" ->
str = " mov %r11, %r13\n"
%{v | u: v.u <> str}
Top.get == 1 && a == "b" ->
str = " mov %r11, %r14\n"
%{v | u: v.u <> str}
Top.get == 1 && a == "c" ->
str = " mov %r11, %r15\n"
%{v | u: v.u <> str}
true ->
str = " set?\n"
%{v | u: v.u <> str}
end
end)
Top.pop
end
def get(a) do
Agent.update(__MODULE__, fn v ->
cond do
Top.get == 0 && a == "a" ->
str = " mov %r13, %r11\n"
%{v | u: v.u <> str}
Top.get == 0 && a == "b" ->
str = " mov %r14, %r11\n"
%{v | u: v.u <> str}
Top.get == 0 && a == "c" ->
str = " mov %r15, %r11\n"
%{v | u: v.u <> str}
Top.get == 1 && a == "a" ->
str = " mov %r13, %r12\n"
%{v | u: v.u <> str}
Top.get == 1 && a == "b" ->
str = " mov %r14, %r12\n"
%{v | u: v.u <> str}
Top.get == 1 && a == "c" ->
str = " mov %r15, %r12\n"
%{v | u: v.u <> str}
true ->
str = " get?\n"
%{v | u: v.u <> str}
end
end)
Top.push
end
def jg(a) do
Agent.update(__MODULE__, fn v ->
str = " jg " <> a <>"\n"
%{v | u: v.u <> str}
end)
Top.pop
end
def jl(a) do
Agent.update(__MODULE__, fn v ->
str = " jl " <> a <>"\n"
%{v | u: v.u <> str}
end)
Top.pop
end
def je(a) do
Agent.update(__MODULE__, fn v ->
str = " je " <> a <>"\n"
%{v | u: v.u <> str}
end)
Top.pop
end
def jmp(a) do
Agent.update(__MODULE__, fn v ->
str = " jmp " <> a <>"\n"
%{v | u: v.u <> str}
end)
#Top.pop
end
def label(a) do
Agent.update(__MODULE__, fn v ->
str = a <> "\n"
%{v | u: v.u <> str}
end)
end
def out() do
Agent.update(__MODULE__, fn v ->
str = " lea msg(%rip), %rdi\n mov %r11, %rax;\n mov %rax, (%rdi)\n mov $1, %rax;\n mov $1, %rdi;\n mov $msg, %rsi;\n mov $1, %rdx;\n syscall;\n"
%{v | u: v.u <> str}
end)
Top.pop
end
def add() do
Agent.update(__MODULE__, fn v ->
str = " mov %r11, %rax\n add %r12, %rax\n mov %rax, %r11\n"
%{v | u: v.u <> str}
end)
Top.pop
end
def sub() do
Agent.update(__MODULE__, fn v ->
str = " mov %r11, %rax\n sub %r12, %rax\n mov %rax, %r11\n"
%{v | u: v.u <> str}
end)
Top.pop
end
def mul() do
Agent.update(__MODULE__, fn v ->
str = " mov %r11, %rax\n mul %r12\n mov %rax, %r11\n"
%{v | u: v.u <> str}
end)
Top.pop
end
def div() do
Agent.update(__MODULE__, fn v ->
str = " mov %r11, %rax\n mov $0, %rdx\n div %r12\n mov %rax, %r11\n"
%{v | u: v.u <> str}
end)
Top.pop
end
def rem() do
Agent.update(__MODULE__, fn v ->
str = " mov %r11, %rax\n mov $0, %rdx\n div %r12\n mov %rdx, %r11\n"
%{v | u: v.u <> str}
end)
Top.pop
end
def gt() do
Agent.update(__MODULE__, fn v ->
str = " mov %r11, %rax\n cmp %r12, %rax\n mov %rax, %r11\n"
%{v | u: v.u <> str}
end)
Top.pop
end
def eq() do
Agent.update(__MODULE__, fn v ->
str = " mov %r11, %rax\n cmp %r12, %rax\n mov %rax, %r11\n"
%{v | u: v.u <> str}
end)
Top.pop
end
def echo() do
Agent.get(__MODULE__, fn v ->
IO.puts ".code64\n.text\n.globl main\nmain:\n" <>
v.u <> "bye:\n mov $60, %rax;\n mov $0, %rdi\n syscall;\n.data\nmsg:\n .asciz \"Hello world!\"\n"
end)
end
def run() do
Agent.get(__MODULE__, fn v ->
File.write "hello.s", ".code64\n.text\n.globl main\nmain:\n" <>
v.u <> "bye:\n mov $60, %rax;\n mov $0, %rdi\n syscall;\n.data\nmsg:\n .asciz \"Hello world!\"\n"
{result, 0} = System.shell("gcc -no-pie hello.s")
IO.puts result
{result, 0} = System.shell("./a.out")
IO.puts result
end)
end
end
defmodule Main do
def run(str) do
Enum.map(String.split(str, "\n"), fn l ->
#IO.puts l
#IO.puts Top.get
s = String.split(l, " ")
cond do
Enum.at(s, 1) == "push" ->
Asm.push(Enum.at(s, 2))
Enum.at(s, 1) == "set" ->
Asm.set(Enum.at(s, 2))
Enum.at(s, 1) == "get" ->
Asm.get(Enum.at(s, 2))
Enum.at(s, 1) == "jg" ->
Asm.jg(Enum.at(s, 2))
Enum.at(s, 1) == "jl" ->
Asm.jl(Enum.at(s, 2))
Enum.at(s, 1) == "je" ->
Asm.je(Enum.at(s, 2))
Enum.at(s, 1) == "jmp" ->
Asm.jmp(Enum.at(s, 2))
Enum.at(s, 0) != "" ->
Asm.label(Enum.at(s, 0))
Enum.at(s, 1) == "out" ->
Asm.out()
Enum.at(s, 1) == "+" ->
Asm.add()
Enum.at(s, 1) == "-" ->
Asm.sub()
Enum.at(s, 1) == "*" ->
Asm.mul()
Enum.at(s, 1) == "/" ->
Asm.div()
Enum.at(s, 1) == "%" ->
Asm.rem()
Enum.at(s, 1) == "<" ->
Asm.gt()
Enum.at(s, 1) == "=" ->
Asm.eq()
true ->
IO.puts Enum.at(s, 1)
end
end)
Asm.run
end
end
Top.start_link
Asm.start_link
Main.run("""
push 0
set a
label20:
get a
push 1
+
set a
get a
push 100
<
jg label255
get a
push 15
%
set b
get b
push 0
=
je label120
get a
push 5
%
set b
get b
push 0
=
je label140
get a
push 3
%
set b
get b
push 0
=
je label160
get a
push 10
/
push 48
+
out
get a
push 10
%
push 48
+
out
push 32
out
jmp label20
label120:
push 102
out
push 105
out
push 122
out
push 122
out
push 98
out
push 117
out
push 122
out
push 122
out
push 32
out
jmp label20
label140:
push 98
out
push 117
out
push 122
out
push 122
out
push 32
out
jmp label20
label160:
push 102
out
push 105
out
push 122
out
push 122
out
push 32
out
jmp label20
label255:
""")
実行結果
01 02 fizz 04 buzz fizz 07 08 fizz buzz 11 fizz 13 14 fizzbuzz 16 17 fizz 19 buzz fizz 22 23 fizz buzz 26 fizz 28 29 fizzbuzz 31 32 fizz 34 buzz fizz 37 38 fizz buzz 41 fizz 43 44 fizzbuzz 46 47 fizz 49 buzz fizz 52 53 fizz buzz 56 fizz 58 59 fizzbuzz 61 62 fizz 64 buzz fizz 67 68 fizz buzz 71 fizz 73 74 fizzbuzz 76 77 fizz 79 buzz fizz 82 83 fizz buzz 86 fizz 88 89 fizzbuzz 91 92 fizz 94 buzz fizz 97 98 fizz buzz
成果物
以上。