Subscribe to RSS Feed ログイン

オーガニック・ウェルス

Wednesday
2018年2月21日

Rust Languageに手を出してみた

Rust a safe, concurrent, practical language

先日「Rust」という新しいプログラミング言語が公開されましたので早速使って見ました。Rustは実行する前にコンパイルをしネイティブの実行ファイルを生成します。

環境はUbuntu 11.10です。


$ sudo apt-get install g++ curl
$ wget http://dl.rust-lang.org/dist/rust-0.1.tar.gz
$ tar xvf rust-0.1.tar.gz
$ cd rust-0.1.tar.gz
$ ./configure
$ make
$ make install

以上で環境構築は終了です。以下のコードを実行してみます。

<hello.rs>

use std;
import std::io;

fn main() {
    for i in [1, 2, 3] {
        io::println(#fmt("hello %d\n", i));
    }
}

 

$ rustc hello.rs
$ ./hello

実行結果

hello 1

hello 2

hello 3

$ ldd hello

	linux-gate.so.1 =>  (0x00c0b000)
	libcore-14bd852465126fe7-0.1.so => /home/user/Programs/rust/./../../../../usr/local/lib/rustc/i686-unknown-linux-gnu/lib/libcore-14bd852465126fe7-0.1.so (0x004a9000)
	libstd-79ca5fac56b63fde-0.1.so => /home/user/Programs/rust/./../../../../usr/local/lib/rustc/i686-unknown-linux-gnu/lib/libstd-79ca5fac56b63fde-0.1.so (0x0098f000)
	librustrt.so => /home/user/Programs/rust/./../../../../usr/local/lib/rustc/i686-unknown-linux-gnu/lib/librustrt.so (0x00b6a000)
	libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0x007e7000)
	libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x00182000)
	libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0x0051a000)
	librt.so.1 => /lib/i386-linux-gnu/librt.so.1 (0x0071d000)
	libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0x00110000)
	libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0x00f40000)
	libstdc++.so.6 => /usr/lib/i386-linux-gnu/libstdc++.so.6 (0x002fe000)
	/lib/ld-linux.so.2 (0x00d87000)

どうやら実行ファイルにRustのライブラリを読み込んでいるようです。この実行ファイルは約16KBとなっています。

objdump -S hello > hello.dump

hello:     file format elf32-i386
~
08048b10 <rust_start@plt>:
 8048b10:	ff 25 2c c0 04 08    	jmp    *0x804c02c
 8048b16:	68 58 00 00 00       	push   $0x58
 8048b1b:	e9 30 ff ff ff       	jmp    8048a50 <_init+0x38>
~
08048b50 <_start>:
 8048b50:	31 ed                	xor    %ebp,%ebp
 8048b52:	5e                   	pop    %esi
 8048b53:	89 e1                	mov    %esp,%ecx
 8048b55:	83 e4 f0             	and    $0xfffffff0,%esp
 8048b58:	50                   	push   %eax
 8048b59:	54                   	push   %esp
 8048b5a:	52                   	push   %edx
 8048b5b:	68 00 9d 04 08       	push   $0x8049d00
 8048b60:	68 90 9c 04 08       	push   $0x8049c90
 8048b65:	51                   	push   %ecx
 8048b66:	56                   	push   %esi
 8048b67:	68 a0 97 04 08       	push   $0x80497a0
 8048b6c:	e8 4f ff ff ff       	call   8048ac0 <__libc_start_main@plt>
 8048b71:	f4                   	hlt
 8048b72:	90                   	nop
 8048b73:	90                   	nop
~

elf形式の実行ファイルを生成しています。

今回は以上です。

続きを読む »

コメント(0)続きを読む

Ubuntuでアセンブラを使ってみる

Ubuntuでアセンブラを始めて見ようと思ったのですが、存在する情報がVistualStudioのインラインアセンブラを前提にしたものばかりでそれ以外のアセンブラ(今回はnasm)での情報がほとんど有りません。

なのでまずC言語でコンパイルした実効ファイルを逆アセンブルしてアセンブルソースを読み解く方法で進めます。

まず以下のC言語のソースから実行ファイルを作成します。

<asmbase.c>

#include <stdio.h>
int add(int a, int b) {
    return a + b;
}
int sub(int a, int b) {
    return a - b;
}
int mul(int a, int b) {
    return a * b;
}
int div(int a, int b) {
    return a / b;
}
float fadd(float a, float b) {
    return a + b;
}
float fsub(float a, float b) {
    return a - b;
}
float fmul(float a, float b) {
    return a * b;
}
float fdiv(float a, float b) {
    return a / b;
}
int main() {
    int i1 = 20, i2 = 4, i3;
    float f1 = 1.5,f2 = 0.3,f3;

    i3 = add(i1, i2);
    printf("add(%d, %d)=%d\n", i1, i2, i3);
    i3 = sub(i1, i2);
    printf("sub(%d, %d)=%d\n", i1, i2, i3);
    i3 = mul(i1, i2);
    printf("mul(%d, %d)=%d\n", i1, i2, i3);
    i3 = div(i1, i2);
    printf("div(%d, %d)=%d\n", i1, i2, i3);

    f3 = fadd(f1, f2);
    printf("fadd(%f, %f)=%f\n", f1, f2, f3);
    f3 = fsub(f1, f2);
    printf("fsub(%f, %f)=%f\n", f1, f2, f3);
    f3 = fmul(f1, f2);
    printf("fmul(%f, %f)=%f\n", f1, f2, f3);
    f3 = fdiv(f1, f2);
    printf("fdiv(%f, %f)=%f\n", f1, f2, f3);
}


$ gcc -o asmbase asmbase.c
$ ./asmbase
add(20, 4)=24
sub(20, 4)=16
mul(20, 4)=80
div(20, 4)=5
fadd(1.500000, 0.300000)=1.800000
fsub(1.500000, 0.300000)=1.200000
fmul(1.500000, 0.300000)=0.450000
fdiv(1.500000, 0.300000)=5.000000

まずasmbaseという実行可能ファイルを作成しました。このファイルを解析します。


$ objdump -S asmbase

(一部抜粋)

~
0804842e <fadd>:
 804842e:	55                   	push   %ebp
 804842f:	89 e5                	mov    %esp,%ebp
 8048431:	d9 45 08             	flds   0x8(%ebp)
 8048434:	d8 45 0c             	fadds  0xc(%ebp)
 8048437:	5d                   	pop    %ebp
 8048438:	c3                   	ret
~

fadd()という関数だけ抜き出してみました。この状態だとAT&T形式(だっけか?)なのでINTEL形式で表示させ直します。私はこの表記の違いでつまづきました。

$ objdump -M intel -S asmbase

~
0804842e <fadd>:
 804842e:	55                   	push   ebp
 804842f:	89 e5                	mov    ebp,esp
 8048431:	d9 45 08             	fld    DWORD PTR [ebp+0x8]
 8048434:	d8 45 0c             	fadd   DWORD PTR [ebp+0xc]
 8048437:	5d                   	pop    ebp
 8048438:	c3                   	ret
~

2つまったく違う表記になりました。特にmovは順番が違います。もちろん意味としては一緒です。内容については詳しく説明できるほど知識が無く、説明できないくて申し訳ないです。

次にこれをもとにCとアセンブラコードを書きます。

<main.c>

#include <stdio.h>

// extern 宣言でアセンブラ内の関数を読み込む
extern int _add(int a, int b);
extern int _sub(int a, int b);
extern int _mul(int a, int b);
extern int _div(int a, int b);
extern float _fadd(float a, float b);
extern float _fsub(float a, float b);
extern float _fmul(float a, float b);
extern float _fdiv(float a, float b);

int main () {
	int i1 = 20, i2 = 4, i3;
	float f1 = 1.5,f2 = 0.3,f3;

	i3 = _add(i1, i2);
	printf("add(%d, %d)=%d\n", i1, i2, i3);
	i3 = _sub(i1, i2);
	printf("sub(%d, %d)=%d\n", i1, i2, i3);
	i3 = _mul(i1, i2);
	printf("mul(%d, %d)=%d\n", i1, i2, i3);
	i3 = _div(i1, i2);
	printf("div(%d, %d)=%d\n", i1, i2, i3);

	f3 = _fadd(f1, f2);
	printf("fadd(%f, %f)=%f\n", f1, f2, f3);
	f3 = _fsub(f1, f2);
	printf("fsub(%f, %f)=%f\n", f1, f2, f3);
	f3 = _fmul(f1, f2);
	printf("fmul(%f, %f)=%f\n", f1, f2, f3);
	f3 = _fdiv(f1, f2);
	printf("fdiv(%f, %f)=%f\n", f1, f2, f3);
    return 0;
}

<sub.s>

    bits 32
	global _add
	global _sub
	global _mul
	global _div
	global _fadd
	global _fsub
	global _fmul
	global _fdiv

    ;; start program area
    section .text

    ;; global functions

_add: ; 二つの引数を足す
    MOV		EDX,[ESP+4]
    ADD		EDX, [ESP+8]
    MOV		EAX, EDX
    RET

_sub: ; 二つの引数をかける
    MOV		EDX,[ESP+4]
    sub		EDX, [ESP+8]
    MOV		EAX, EDX
    RET

_mul: ; 二つの引数をかける
    MOV		eax,[ESP+4]
    mov		ebx,[ESP+8]
    mul		ebx
    RET

_div: ; 二つの引数をかける
    MOV		eax,[ESP+4]
    mov		ebx,[ESP+8]
    div		ebx
    RET

_fadd: ; 2つの実数を足す
	push	ebp
	mov		ebp, esp
	fld		DWORD [ebp+8]
	fadd	DWORD [ebp+12]
	pop		ebp
    RET

_fsub: ; 2つの実数を引く
	push	ebp
	mov		ebp, esp
	fld		DWORD [ebp+8]
	fsub	DWORD [ebp+12]
	pop		ebp
    RET

_fmul: ; 2つの実数を掛ける
	push	ebp
	mov		ebp, esp
	fld		DWORD [ebp+8]
	fmul	DWORD [ebp+12]
	pop		ebp
    RET

_fdiv: ; 2つの実数を割る
	push	ebp
	mov		ebp, esp
	fld		DWORD [ebp+8]
	fdiv	DWORD [ebp+12]
	pop		ebp
    RET

上記2つのコードをビルドします。

$ gcc -o main.o -c main.c
$ nasm -f elf32 -o sub.o sub.s
$ gcc -o main main.o sub.o
$ ./main

実行結果

add(20, 4)=24
sub(20, 4)=16
mul(20, 4)=80
div(20, 4)=5
fadd(1.500000, 0.300000)=1.800000
fsub(1.500000, 0.300000)=1.200000
fmul(1.500000, 0.300000)=0.450000
fdiv(1.500000, 0.300000)=5.000000

とCのソースからアセンブラのソースが呼び出せました。

コメント(2)続きを読む

PHPの処理の確かめスクリプト

PHPの処理系で分からない部分があったので確かめる処理を書いてみました。特に”0x0A”と”10″を単純に文字比較すると等しいと判定されるので注意が必要です。

実行環境はWindows7 PHP5.3.5です。

PHPのソース(SHIFT-JIS)

<?php
echo '"0x0A" == "10"'." => ".var_export("0x0A" == "10", true).PHP_EOL;
echo '"0x0A" === "10"'." => ".var_export("0x0A" === "10", true).PHP_EOL;
echo '"0x0A" == 10'." => ".var_export("0x0A" == 10, true).PHP_EOL;
echo '"0x0A" === 10'." => ".var_export("0x0A" === 10, true).PHP_EOL;
echo '10 == "10"'." => ".var_export(10 == "10", true).PHP_EOL;
echo '10 === "10"'." => ".var_export(10 === "10", true).PHP_EOL;
echo '10 == "a"'." => ".var_export(10 == "a", true).PHP_EOL;
echo '10 === "a"'." => ".var_export(10 === "a", true).PHP_EOL;
echo '"00" == "0"'." => ".var_export("00" == "0", true).PHP_EOL;
echo '"-0" == "00000"'." => ".var_export("-0" == "00000", true).PHP_EOL;
echo '"00" === "0"'." => ".var_export("00" === "0", true).PHP_EOL;
echo '"-0" === "00000"'." => ".var_export("-0" === "00000", true).PHP_EOL;
echo 'false == 0'." => ".var_export(false == 0, true).PHP_EOL;
echo 'NULL == 0'." => ".var_export(NUll == 0, true).PHP_EOL;
echo 'false === 0'." => ".var_export(false === 0, true).PHP_EOL;
echo 'NULL === 0'." => ".var_export(NUll === 0, true).PHP_EOL;
echo 'NULL == false'." => ".var_export(NUll == false, true).PHP_EOL;
echo 'NULL === false'." => ".var_export(NUll === false, true).PHP_EOL;
echo '$bool = false'.PHP_EOL;($bool = false);
echo 'isset($bool)'." => ".var_export(isset($bool), true).PHP_EOL;
echo '$bool = NULL'.PHP_EOL;($bool = NULL);
echo 'isset($bool)'." => ".var_export(isset($bool), true).PHP_EOL;
echo '$bool = 0'.PHP_EOL;($bool = 0);
echo 'isset($bool)'." => ".var_export(isset($bool), true).PHP_EOL;

echo PHP_EOL;

echo 'is_int(10)'." => ".var_export(is_int(10), true).PHP_EOL;
echo 'is_int("10")'." => ".var_export(is_int("10"), true).PHP_EOL;
echo 'is_string("10")'." => ".var_export(is_string("10"), true).PHP_EOL;
echo 'is_int(true)'." => ".var_export(is_int(true), true).PHP_EOL;
echo 'is_int(false)'." => ".var_export(is_int(false), true).PHP_EOL;
echo 'is_int("true")'." => ".var_export(is_int("true"), true).PHP_EOL;
echo 'is_int("false")'." => ".var_export(is_int("false"), true).PHP_EOL;
echo 'is_string(true)'." => ".var_export(is_string(true), true).PHP_EOL;
echo 'is_string(false)'." => ".var_export(is_string(false), true).PHP_EOL;
echo 'is_string("true")'." => ".var_export(is_string("true"), true).PHP_EOL;
echo 'is_string("false")'." => ".var_export(is_string("false"), true).PHP_EOL;
echo 'is_bool(true)'." => ".var_export(is_bool(true), true).PHP_EOL;
echo 'is_bool(false)'." => ".var_export(is_bool(false), true).PHP_EOL;
echo 'is_bool("true")'." => ".var_export(is_bool("true"), true).PHP_EOL;
echo 'is_bool("false")'." => ".var_export(is_bool("false"), true).PHP_EOL;
echo 'is_bool(0)'." => ".var_export(is_bool(0), true).PHP_EOL;
echo 'is_bool(1)'." => ".var_export(is_bool(1), true).PHP_EOL;
echo PHP_EOL;

echo '@is_int(A)'." => ".var_export(@is_int(A), true).PHP_EOL;
echo '@is_string(A)'." => ".var_export(@is_string(A), true).PHP_EOL;
echo PHP_EOL;

$str = '
$var = NULL;
if($var) $res = true;
else $res = false;
return $res;';
echo $str." => ".var_export(eval($str), true).PHP_EOL;

$str = '
$var = 0;
if($var) $res = true;
else $res = false;
return $res;';
echo $str." => ".var_export(eval($str), true).PHP_EOL;

$str = '
$var = 1;
if($var) $res = true;
else $res = false;
return $res;';
echo $str." => ".var_export(eval($str), true).PHP_EOL;

$str = '
$var = -1;
if($var) $res = true;
else $res = false;
return $res;';
echo $str." => ".var_export(eval($str), true).PHP_EOL;

$str = '
$var = "";
if($var) $res = true;
else $res = false;
return $res;';
echo $str." => ".var_export(eval($str), true).PHP_EOL;

$str = '
$var = array();
if($var) $res = true;
else $res = false;
return $res;';
echo $str." => ".var_export(eval($str), true).PHP_EOL;

$str = '
$var = array(1);
if($var) $res = true;
else $res = false;
return $res;';
echo $str." => ".var_export(eval($str), true).PHP_EOL;

echo PHP_EOL;

echo 'strlen("あいう")'." => ".var_export(strlen("あいう"), true).PHP_EOL;
echo 'mb_strlen("あいう")'." => ".var_export(mb_strlen("あいう"), true).PHP_EOL;

echo PHP_EOL;
echo 'mb_language("Japanese");'.PHP_EOL;
mb_language("Japanese");

echo 'strlen("あいう")'." => ".var_export(strlen("あいう"), true).PHP_EOL;
echo 'mb_strlen("あいう")'." => ".var_export(mb_strlen("あいう"), true).PHP_EOL;

echo PHP_EOL;
echo 'mb_internal_encoding("SHIFT-JIS");'.PHP_EOL;
mb_internal_encoding("SHIFT-JIS");

echo 'strlen("あいう")'." => ".var_export(strlen("あいう"), true).PHP_EOL;
echo 'mb_strlen("あいう")'." => ".var_export(mb_strlen("あいう"), true).PHP_EOL;

echo PHP_EOL;

echo '$str = "abc"'.PHP_EOL;$str = "abc";
echo '$str{0}'." => ".var_export($str{0}, true).PHP_EOL;
echo '$str = "あいう"'.PHP_EOL;$str = "あいう";
echo '$str{0}'." => ".var_export($str{0}, true).PHP_EOL;

echo PHP_EOL;

$str = "abcd";
echo 'unpack("C*", "'.$str.'") => '.var_export(unpack("C*", $str), true).PHP_EOL;

echo PHP_EOL;
echo 'pack("C*", 97, 98, 99, 100) => '.var_export(pack("C*", 97, 98, 99, 100), true).PHP_EOL;

echo PHP_EOL;
echo 'pack("C*", 97, 98, 0, 99, 100) => '.var_export(pack("C*", 97, 98, 0, 99, 100), true).PHP_EOL;

echo PHP_EOL;
$str = pack("C*", 97, 98, 0, 99, 100);
echo '$str = pack("C*", 97, 98, 0, 99, 100)'.PHP_EOL;
echo 'is_string($str) => '.var_export(is_string($str), true).PHP_EOL;
echo 'strlen($str) => '.var_export(strlen($str), true).PHP_EOL;
echo 'mb_strlen($str) => '.var_export(mb_strlen($str), true).PHP_EOL;
echo 'strstr($str, "\0") => '.var_export(strstr($str, "\0"), true).PHP_EOL;
echo 'unpack("C*", $str) => '.var_export(unpack("C*", $str), true).PHP_EOL;

 

echo 'str_replace("\0", "-", $str) => '.var_export(str_replace("\0", "-", $str), true).PHP_EOL;

実行結果


"0x0A" == "10" => true
"0x0A" === "10" => false
"0x0A" == 10 => true
"0x0A" === 10 => false
10 == "10" => true
10 === "10" => false
10 == "a" => false
10 === "a" => false
"00" == "0" => true
"-0" == "00000" => true
"00" === "0" => false
"-0" === "00000" => false
false == 0 => true
NULL == 0 => true
false === 0 => false
NULL === 0 => false
NULL == false => true
NULL === false => false
$bool = false
isset($bool) => true
$bool = NULL
isset($bool) => false
$bool = 0
isset($bool) => true

is_int(10) => true
is_int("10") => false
is_string("10") => true
is_int(true) => false
is_int(false) => false
is_int("true") => false
is_int("false") => false
is_string(true) => false
is_string(false) => false
is_string("true") => true
is_string("false") => true
is_bool(true) => true
is_bool(false) => true
is_bool("true") => false
is_bool("false") => false
is_bool(0) => false
is_bool(1) => false

@is_int(A) => false
@is_string(A) => true

$var = NULL;
if($var) $res = true;
else $res = false;
return $res; => false

$var = 0;
if($var) $res = true;
else $res = false;
return $res; => false

$var = 1;
if($var) $res = true;
else $res = false;
return $res; => true

$var = -1;
if($var) $res = true;
else $res = false;
return $res; => true

$var = "";
if($var) $res = true;
else $res = false;
return $res; => false

$var = array();
if($var) $res = true;
else $res = false;
return $res; => false

$var = array(1);
if($var) $res = true;
else $res = false;
return $res; => true

strlen("あいう") => 6
mb_strlen("あいう") => 6

mb_language("Japanese");
strlen("あいう") => 6
mb_strlen("あいう") => 6

mb_internal_encoding("SHIFT-JIS");
strlen("あいう") => 6
mb_strlen("あいう") => 3

$str = "abc"
$str{0} => 'a'
$str = "あいう"
$str{0} => '・

unpack("C*", "abcd") => array (
1 => 97,
2 => 98,
3 => 99,
4 => 100,
)

pack("C*", 97, 98, 99, 100) => 'abcd'

pack("C*", 97, 98, 0, 99, 100) => 'ab' . "\0" . 'cd'

 

$str = pack("C*", 97, 98, 0, 99, 100)
is_string($str) => true
strlen($str) => 5
mb_strlen($str) => 5
strstr($str, "\0") => '' . "\0" . 'cd'
unpack("C*", $str) => array (
1 => 97,
2 => 98,
3 => 0,
4 => 99,
5 => 100,
)
str_replace("\0", "-", $str) => 'ab-cd'

コメント(0)続きを読む