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


実行結果


.code64
.text
.globl main
main:
    mov 	$1, %r11
    mov 	%r11, %r13
    mov 	$1, %r11
    mov 	%r11, %r14
label30:
    mov 	%r13, %r11
    mov 	%r14, %r12
    mov		%r11, %rax
    mul		%r12
    mov		%rax, %r11
    mov 	%r11, %r15
    mov 	%r15, %r11
    mov 	$10, %r12
    mov		%r11, %rax
	mov	 	$0, %rdx
    div		%r12
    mov		%rax, %r11
    mov 	$48, %r12
    mov		%r11, %rax
    add		%r12, %rax
    mov		%rax, %r11
    lea	 	msg(%rip), %rdi
    mov   	%r11, %rax;
    mov	        %rax, (%rdi)
    mov   	$1, %rax;
    mov   	$1, %rdi;
    mov   	$msg, %rsi;
    mov   	$1, %rdx;
    syscall;
label31:
    mov 	%r15, %r11
    mov 	$10, %r12
    mov		%r11, %rax
	mov	 	$0, %rdx
    div		%r12
    mov		%rdx, %r11
    mov 	$48, %r12
    mov		%r11, %rax
    add		%r12, %rax
    mov		%rax, %r11
    lea	 	msg(%rip), %rdi
    mov   	%r11, %rax;
    mov	        %rax, (%rdi)
    mov   	$1, %rax;
    mov   	$1, %rdi;
    mov   	$msg, %rsi;
    mov   	$1, %rdx;
    syscall;
label32:
    mov 	$32, %r11
    lea	 	msg(%rip), %rdi
    mov   	%r11, %rax;
    mov	        %rax, (%rdi)
    mov   	$1, %rax;
    mov   	$1, %rdi;
    mov   	$msg, %rsi;
    mov   	$1, %rdx;
    syscall;
label33:
    mov 	%r13, %r11
    mov 	$1, %r12
    mov		%r11, %rax
    add		%r12, %rax
    mov		%rax, %r11
    mov 	%r11, %r13
    mov 	%r13, %r11
    mov 	$10, %r12
    mov		%r11, %rax
    cmp		%r12, %rax
    mov		%rax, %r11
    jl   label30
    mov 	$10, %r11
    lea	 	msg(%rip), %rdi
    mov   	%r11, %rax;
    mov	        %rax, (%rdi)
    mov   	$1, %rax;
    mov   	$1, %rdi;
    mov   	$msg, %rsi;
    mov   	$1, %rdx;
    syscall;
label34:
    mov 	%r14, %r11
    mov 	$1, %r12
    mov		%r11, %rax
    add		%r12, %rax
    mov		%rax, %r11
    mov 	%r11, %r14
    mov 	$1, %r11
    mov 	%r11, %r13
    mov 	%r14, %r11
    mov 	$10, %r12
    mov		%r11, %rax
    cmp		%r12, %rax
    mov		%rax, %r11
    jl   label30
bye:
    mov   	$60, %rax;
    mov 	$0, %rdi
    syscall;
.data
msg:
	.asciz "Hello world!"

成果物

以上。

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