LoginSignup
1
0

More than 1 year has passed since last update.

概要

paiza.ioでelixirやってみた。
練習問題やってみた。

練習問題

俺cpuのアセンブラから、x64アセンブラを生成し、コンパイル、実行せよ。

サンプルコード

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 ->
			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 jz(a) do
		Agent.update(__MODULE__, fn v ->
			str = "    jl   " <> 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 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 ->
			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) == "jz" ->
				Asm.jz(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()
			true ->
				IO.puts Enum.at(s, 1)
			end
		end)
		Asm.run
	end
end

Top.start_link
Asm.start_link

Main.run("""
  push  1
  set  a
  push  1
  set  b
label30:
  get  a
  get  b
  *  
  set  c
  get  c
  push  10
  /  
  push  48
  +  
  out
label31:
  get  c
  push  10
  %  
  push  48
  +  
  out
label32:
  push  32
  out  	
label33:
  get  a
  push  1
  +  
  set  a
  get  a
  push  10
  <  
  jz  label30
  push  10
  out  
label34:
  get  b
  push  1
  +  
  set  b
  push  1
  set  a
  get  b
  push  10
  <  
  jz  label30
""")


実行結果



01 02 03 04 05 06 07 08 09 
02 04 06 08 10 12 14 16 18 
03 06 09 12 15 18 21 24 27 
04 08 12 16 20 24 28 32 36 
05 10 15 20 25 30 35 40 45 
06 12 18 24 30 36 42 48 54 
07 14 21 28 35 42 49 56 63 
08 16 24 32 40 48 56 64 72 
09 18 27 36 45 54 63 72 81 

成果物

以上。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0