<?xml version="1.0" encoding="utf-8" ?><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/rss/1.0/" 
			xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" 
			xmlns:cc="http://web.resource.org/cc/" xml:lang="ja">
<channel rdf:about="http://mkosaki.blog46.fc2.com/?xml">
<title>革命の日々！</title>
<link>http://mkosaki.blog46.fc2.com/</link>
<description>５７は素数ですが何か？</description>
<dc:language>ja</dc:language>
<items>
<rdf:Seq>
<rdf:li rdf:resource="http://mkosaki.blog46.fc2.com/blog-entry-1073.html" />
<rdf:li rdf:resource="http://mkosaki.blog46.fc2.com/blog-entry-1071.html" />
<rdf:li rdf:resource="http://mkosaki.blog46.fc2.com/blog-entry-1070.html" />
<rdf:li rdf:resource="http://mkosaki.blog46.fc2.com/blog-entry-1069.html" />
<rdf:li rdf:resource="http://mkosaki.blog46.fc2.com/blog-entry-1068.html" />
</rdf:Seq>
</items>
</channel>
<item rdf:about="http://mkosaki.blog46.fc2.com/blog-entry-1073.html">
<link>http://mkosaki.blog46.fc2.com/blog-entry-1073.html</link>
<title>80文字は短すぎる</title>
<description> 80文字は現代的じゃないから120文字にしようというパッチが投稿From: Stefani Seibold Subject: [PATCH] checkpatch.pl: remove the 80 charactes punch card limitThe time of 80 characters punch card and terminals are over, so i wouldbe a good thing to set the line length limit to 120. Every display todayshould be able handle this.   Signed-off-by: Stefani Seibold --- checkpatch.pl |    6 +++--- 1 file chan
 </description>
<content:encoded>
<![CDATA[ 80文字は現代的じゃないから120文字にしようというパッチが投稿<br /><br /><blockquote><pre><br />From: Stefani Seibold <stefani@seibold.net><br />Subject: [PATCH] checkpatch.pl: remove the 80 charactes punch card limit<br /><br />The time of 80 characters punch card and terminals are over, so i would<br />be a good thing to set the line length limit to 120. Every display today<br />should be able handle this. <br />  <br />Signed-off-by: Stefani Seibold <stefani@seibold.net><br />---<br /> checkpatch.pl |    6 +++---<br /> 1 file changed, 3 insertions(+), 3 deletions(-)<br /><br />--- linux-2.6.33-rc2.orig/scripts/checkpatch.pl	2009-12-03 04:51:21.000000000 +0100<br />+++ linux-2.6.33-rc2.new/scripts/checkpatch.pl	2010-01-06 17:46:40.057565661 +0100<br />@@ -1374,13 +1374,13 @@ sub process {<br /> # check we are in a valid source file if not then ignore this hunk<br /> 		next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/);<br /> <br />-#80 column limit<br />+#120 column limit<br /> 		if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ &&<br /> 		    $rawline !~ /^.\s*\*\s*\@$Ident\s/ &&<br /> 		    $line !~ /^\+\s*printk\s*\(\s*(?:KERN_\S+\s*)?"[X\t]*"\s*(?:,|\)\s*;)\s*$/ &&<br />-		    $length > 80)<br />+		    $length > 120)<br /> 		{<br />-			WARN("line over 80 characters\n" . $herecurr);<br />+			WARN("line over 120 characters\n" . $herecurr);<br /> 		}<br /> <br /> # check for adding lines without a newline.<br /><br /></pre></blockquote><br /><br />Andi Kleen登場<br /><br /><blockquote><pre><br />> The time of 80 characters punch card and terminals are over, so i would<br />> be a good thing to set the line length limit to 120. Every display today<br />> should be able handle this. <br />>   <br />> Signed-off-by: Stefani Seibold <stefani@seibold.net><br /><br />Full Ack!<br /><br />-Andi</pre></blockquote><br /><br /><br />撃沈<br /><br /><blockquote><pre><br />>> The time of 80 characters punch card and terminals are over, so i would<br />>> be a good thing to set the line length limit to 120. Every display today<br />>> should be able handle this. <br />>>   <br />>> Signed-off-by: Stefani Seibold <stefani@seibold.net><br />> <br />> Full Ack!<br />> <br />NACK Attack!<br /><br />There is a reason Knuth only put so many words on a line with TeX.<br /><br />Eugh.<br /><br />Cheers</pre></blockquote><br /><br /><br />やはり１４０文字にしなかったのが敗因か ← ちがいます<br /><br />Knuthのくだりは何がいいたいのかよく分からんかった<br />どうでもいいけど、マジメに議論する気がないのがヒシヒシと伝わってくるいいメールだな。お互いに<br /><br /> ]]>
</content:encoded>
<dc:subject>linux</dc:subject>
<dc:date>2010-01-29T11:03:39+09:00</dc:date>
<dc:creator>kosaki</dc:creator>
<dc:publisher>FC2-BLOG</dc:publisher>
</item>
<item rdf:about="http://mkosaki.blog46.fc2.com/blog-entry-1071.html">
<link>http://mkosaki.blog46.fc2.com/blog-entry-1071.html</link>
<title>akrパッチがマージされたらしい</title>
<description> 中身はまったく把握してないが、akrさんが巨大なドライバパッチ（3000行越え！）を-mmにねじ込んだようだ。（From行に注目）すごいなーThe patch titled     SIS USB2VGA DRIVER: support KAIREN's USB VGA adaptor USB20SVGA-MB-PLUShas been added to the -mm tree.  Its filename is     sis-usb2vga-driver-support-kairens-usb-vga-adaptor-usb20svga-mb-plus.patchBefore you just go and hit &quot;reply&quot;, please:   a) Conside
 </description>
<content:encoded>
<![CDATA[ 中身はまったく把握してないが、akrさんが巨大なドライバパッチ（3000行越え！）を-mmにねじ込んだようだ。<br />（From行に注目）<br /><br />すごいなー<br /><br /><blockquote><pre><br />The patch titled<br />     SIS USB2VGA DRIVER: support KAIREN's USB VGA adaptor USB20SVGA-MB-PLUS<br />has been added to the -mm tree.  Its filename is<br />     sis-usb2vga-driver-support-kairens-usb-vga-adaptor-usb20svga-mb-plus.patch<br /><br />Before you just go and hit "reply", please:<br />   a) Consider who else should be cc'ed<br />   b) Prefer to cc a suitable mailing list as well<br />   c) Ideally: find the original patch on the mailing list and do a<br />      reply-to-all to that, adding suitable additional cc's<br /><br />*** Remember to use Documentation/SubmitChecklist when testing your code ***<br /><br />See http://userweb.kernel.org/~akpm/stuff/added-to-mm.txt to find<br />out what to do about this<br /><br />The current -mm tree may be found at http://userweb.kernel.org/~akpm/mmotm/<br /><br />------------------------------------------------------<br />Subject: SIS USB2VGA DRIVER: support KAIREN's USB VGA adaptor USB20SVGA-MB-PLUS<br />From: Tanaka Akira &lt;akr _at_ fsij.org&gt;<br /><br />Add the USB product ID of KAIREN's USB VGA Adaptor, USB20SVGA-MB-PLUS, to<br />make sisusbvga work with it.<br /><br />Signed-off-by: Tanaka Akira &lt;akr _at_ fsij.org&gt;<br />Cc: Thomas Winischhofer &lt;thomas@winischhofer.net&gt;<br />Cc: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;<br />Signed-off-by: Andrew Morton &lt;akpm@linux-foundation.org&gt;<br />---<br /><br /> drivers/usb/misc/sisusbvga/sisusb.c      |    1 <br /> drivers/usb/misc/sisusbvga/sisusb.c.orig | 3293 +++++++++++++++++++++<br /> 2 files changed, 3294 insertions(+)<br /><br />（略）<br /></pre></blockquote> ]]>
</content:encoded>
<dc:subject>linux</dc:subject>
<dc:date>2010-01-26T10:26:44+09:00</dc:date>
<dc:creator>kosaki</dc:creator>
<dc:publisher>FC2-BLOG</dc:publisher>
</item>
<item rdf:about="http://mkosaki.blog46.fc2.com/blog-entry-1070.html">
<link>http://mkosaki.blog46.fc2.com/blog-entry-1070.html</link>
<title>git commit時に自動的にcheckpatch.pl してくれるpre-commitスクリプト</title>
<description> なんてものが、LKMLに投稿されているなDate:	Wed, 20 Jan 2010 02:02:02 +0000From:	Ben Dooks To:	linux-arm-kernel@lists.infradead.org, Linux Samsung SoC , Linux Kernel Subject: git pre-commit hook running checkpatch.plI've written a git pre-commit[1] hook which stops any commits happening ifcheckpatch.pl reports problems with the patch. Any comments?[1] http://www.fluff.org/ben/linux/githooks/pre-comm
 </description>
<content:encoded>
<![CDATA[ なんてものが、LKMLに投稿されているな<br /><br /><blockquote><p><br />Date:	Wed, 20 Jan 2010 02:02:02 +0000<br />From:	Ben Dooks <ben-linux@fluff.org><br />To:	linux-arm-kernel@lists.infradead.org,<br /> Linux Samsung SoC <linux-samsung-soc@vger.kernel.org>,<br /> Linux Kernel <linux-kernel@vger.kernel.org><br />Subject: git pre-commit hook running checkpatch.pl<br /><br />I've written a git pre-commit[1] hook which stops any commits happening if<br />checkpatch.pl reports problems with the patch. Any comments?<br /><br />[1] http://www.fluff.org/ben/linux/githooks/pre-commit<br /><br />-- <br />Ben<br /><br />Q:      What's a light-year?<br />A:      One-third less calories than a regular year.<br /><br /></p></blockquote><br /><br />リンク切れに備えて、直接はっておこう<br /><blockquote><pre><br />#!/bin/sh<br />#<br /># pre-commit hook to run check-patch on the output and stop any commits<br /># that do not pass. Note, only for git-commit, and not for any of the<br /># other scenarios<br />#<br /># Copyright 2010 Ben Dooks, <ben-linux@fluff.org><br /><br />if git rev-parse --verify HEAD 2>/dev/null >/dev/null<br />then<br />	against=HEAD<br />else<br />	# Initial commit: diff against an empty tree object<br />	against=4b825dc642cb6eb9a060e54bf8d69288fbee4904<br />fi<br /><br />git diff --cached $against -- | ./scripts/checkpatch.pl --no-signoff -<br /><br /></pre></blockquote><br /><br /> ]]>
</content:encoded>
<dc:subject>linux</dc:subject>
<dc:date>2010-01-20T11:10:53+09:00</dc:date>
<dc:creator>kosaki</dc:creator>
<dc:publisher>FC2-BLOG</dc:publisher>
</item>
<item rdf:about="http://mkosaki.blog46.fc2.com/blog-entry-1069.html">
<link>http://mkosaki.blog46.fc2.com/blog-entry-1069.html</link>
<title>Rubyで学ぶx86_64 ABI</title>
<description> ひさしぶりにプログラミングの話題でも。現在のRubyのtrunkをx86_64上のFedora12でmake test-allすると8個ぐらいテストが失敗するのだが、その中の１つにこういうエラーがある  1) Failure:test_sin(DL::TestDL) [/home/kosaki/linux/ruby/test/dl/test_dl2.rb:95]: expected but was.test/dl/test_dl2.rbというのが、なにをしているテストかというと、ようするに以下のようにdlモジュールを使ってlibmのsin関数を呼んでいるわけだ
 </description>
<content:encoded>
<![CDATA[ ひさしぶりにプログラミングの話題でも。<br />現在のRubyのtrunkをx86_64上のFedora12でmake test-allすると8個ぐらいテストが失敗するのだが、その中の１つにこういうエラーがある<br /><br /><blockquote><pre>  1) Failure:<br />test_sin(DL::TestDL) [/home/kosaki/linux/ruby/test/dl/test_dl2.rb:95]:<br /><1.0> expected but was<br /><1.38523885234213e-309>.<br /></pre></blockquote><br /><br />test/dl/test_dl2.rbというのが、なにをしているテストかというと、ようするに以下のようにdlモジュールを使ってlibmのsin関数を呼んでいるわけだ<br /><br /><blockquote><pre>module DL<br />class TestDL < TestBase<br />  # TODO: refactor test repetition<br />  def test_sin()<br />    pi_2 = Math::PI/2<br />    cfunc = CFunc.new(@libm['sin'], TYPE_DOUBLE, 'sin')<br />    x = cfunc.call([pi_2].pack("d").unpack("l!*"))<br />    assert_equal(Math.sin(pi_2), x)<br />  end<br />end<br />end # module DL<br /></pre></blockquote><br /><br />dlモジュールというのは（僕は知らなかったのだが）RubyからCのコードを直接呼ぶためのしくみで、引数をpackとunpackを使ってlongの配列にしておくと、なぜか関数の型に関わらず正しい結果がかえって来るという魔法のライブラリである。<br /><br />まあ sin(π/2）が1.0にならなかったら、バグだよね。<br /><br /><br />では、その実装をみていこう<br /><br /><blockquote><pre><br />static VALUE<br />rb_dlcfunc_call(VALUE self, VALUE ary)<br />{<br />    struct cfunc_data *cfunc;<br />    int i;<br />    DLSTACK_TYPE stack[DLSTACK_SIZE];<br />    VALUE result = Qnil;<br /><br />    rb_secure_update(self);<br /><br />    memset(stack, 0, sizeof(DLSTACK_TYPE) * DLSTACK_SIZE);<br />    Check_Type(ary, T_ARRAY);<br /><br />    TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, cfunc);<br /><br />    if( cfunc->ptr == 0 ){<br />        rb_raise(rb_eDLError, "can't call null-function");<br />        return Qnil;<br />    }<br /><br />    for( i = 0; i < RARRAY_LEN(ary); i++ ){<br />        if( i >= DLSTACK_SIZE ){<br />            rb_raise(rb_eDLError, "too many arguments (stack overflow)");<br />        }<br />        rb_check_safe_obj(RARRAY_PTR(ary)[i]);<br />        stack[i] = NUM2LONG(RARRAY_PTR(ary)[i]);<br />    }<br /></pre></blockquote><br /><br />まず、RubyのArray（ary）をCのArray（stack[])に変換する。<br /><br /><blockquote><pre><br />        switch( cfunc->type ){<br />        case DLTYPE_VOID:<br />#define CASE(n) case n: { \<br />            DECL_FUNC_CDECL(f,void,DLSTACK_PROTO##n) = cfunc->ptr; \<br />            f(DLSTACK_ARGS##n(stack)); \<br />            result = Qnil; \<br />}<br />            CALL_CASE;<br />#undef CASE<br />            break;<br />・・・<br /><br />        case DLTYPE_DOUBLE:<br />#define CASE(n) case n: { \<br />            DECL_FUNC_CDECL(f,double,DLSTACK_PROTO##n) = cfunc->ptr; \<br />            double ret; \<br />            ret = f(DLSTACK_ARGS##n(stack));    \<br />            result = rb_float_new(ret); \<br />}<br />            CALL_CASE;<br />#undef CASE<br /></pre></blockquote><br /><br />んで、CFunc.newで渡したtypeに応じてクソ長い switch caseが始まる。ここでさらに引数の数に応じて場合分けしたいが最大引数数がrubyのdlモジュールの仕様上20個もあるため、いちいち書くのがめんどくさいのでCASE, CALLCASEマクロで量産している。CALL_CASEマクロの定義は以下<br /><br /><blockquote><pre><br />#define CALL_CASE switch( RARRAY_LEN(ary) ){ \<br />  CASE(0); break; \<br />  CASE(1); break; CASE(2); break; CASE(3); break; CASE(4); break; CASE(5); break; \<br />  CASE(6); break; CASE(7); break; CASE(8); break; CASE(9); break; CASE(10);break; \<br />  CASE(11);break; CASE(12);break; CASE(13);break; CASE(14);break; CASE(15);break; \<br />  CASE(16);break; CASE(17);break; CASE(18);break; CASE(19);break; CASE(20);break; \<br />  default: rb_raise(rb_eArgError, "too many arguments"); \<br />}</pre></blockquote><br /><br />というわけで、cfunc.call()すると<br /><br /><blockquote><pre><br />            DECL_FUNC_CDECL(f,double,DLSTACK_PROTO##n) = cfunc->ptr; \<br /></pre></blockquote><br /><br />はCFunc.newでlookupした関数ポインタcfunc->ptr（この場合はsin())をｆに代入して、<br /><br /><blockquote><pre><br />            double ret; \<br />            ret = f(DLSTACK_ARGS##n(stack));    \<br /></pre></blockquote><br /><br />ｆをcallして<br /><br /><blockquote><pre><br />            result = rb_float_new(ret); \<br /></pre></blockquote><br /><br />それをrubyのfloatオブジェクトに変換して返す。ということをしているのだと分かる。実装の詳細を見るために<br />DLSTACK_PROTO1<br />DECL_FUNC_CDECL<br />DLSTACK_ARGS1<br />のマクロ定義も見ていこう。（あ、今回は引数１つなので##nは1になる。CALL_CASEマクロをもう一度みると納得できると思います。）<br /><br />まず、DLSTACK_PROTO1とDECL_FUNC_CDECLから見る<br /><blockquote><pre><br />#define DLSTACK_TYPE long<br />#define DLSTACK_PROTO1_ DLSTACK_TYPE<br />#define DLSTACK_PROTO1 DLSTACK_PROTO1_, ...<br /><br />#if !defined(FUNC_CDECL)<br />#  define FUNC_CDECL(x) x<br />#endif<br /># define DECL_FUNC_CDECL(f,ret,args)  ret (FUNC_CDECL(*f))(args)<br /></pre></blockquote><br /><br />ようするに DLSTACK_PROTO1 → "long, ..." で結果として<br /><br />            DECL_FUNC_CDECL(f,double,DLSTACK_PROTO##n) = cfunc->ptr; \<br /><br />という行は<br /><br />double (*f)(long, ...) = cfunc->ptr;<br /><br />となる。<br /><br />わざわざ可変長引数にしている理由は、すぐそばに以下のコメントががが<br /><blockquote><pre><br />/*<br /> * Add ",..." as the last argument.<br /> * This is required for variable argument functions such<br /> * as fprintf() on x86_64-linux.<br /> *<br /> * http://refspecs.linuxfoundation.org/elf/x86_64-abi-0.95.pdf<br /> * page 19:<br /> *<br /> *   For calls that may call functions that use varargs or stdargs<br /> *   (prototype-less calls or calls to functions containing ellipsis<br /> *   (...) in the declaration) %al is used as hidden argument to<br /> *   specify the number of SSE registers used.<br /> */<br /></pre></blockquote><br /><br />つまり、x86_64では...を特別扱いするから、これでうまくいくんだよ。と言いたいようだ。<br /><br />でもって、DLSTACK_ARGS1は<br /><br /><blockquote><pre><br />#define DLSTACK_ARGS1(stack) stack[0]<br /></pre></blockquote><br /><br />なので、<br /><br />            f(DLSTACK_ARGS##n(stack)); \<br /><br />は<br /><br />f(stack[0]);<br /><br />という普通の関数呼び出しになる。<br /><br />あれ？なんかx86_64対策も入ってるのになんでうまくいかんのだ？という話になるので、参照されているx86_64 ABI<br />の原典を読む<br /><br /><br /><blockquote><pre><br /><b>3.2.3 Parameter Passing</b><br /><br />After the argument values have been computed, they are placed in registers, or<br />pushed on the stack. The way how values are passed is described in the following<br />sections.<br /><br />Definitions We first define a number of classes to classify arguments. The<br />classes are corresponding to AMD64 register classes and defined as:<br /><br /><b>INTEGER</b> This class consists of integral types that fit into one of the general<br />        purpose registers.<br /><b>SSE</b> The class consists of types that fits into a SSE register.<br /><b>SSEUP</b> The class consists of types that fit into a SSE register and can be passed<br />      and returned in the most significant half of it.<br /><b>X87, X87UP</b> These classes consists of types that will be returned via the x87 FPU.<br /><b>COMPLEX_X87</b> This class consists of types that will be returned via the x87 FPU.<br /><b>NO_CLASS</b> This class is used as initializer in the algorithms. It will be used for<br />         padding and empty structures and unions.<br /><b>MEMORY</b> This class consists of types that will be passed and returned in memory<br />        via the stack.<br /></pre></blockquote><br /><br />超訳。ABI的にはINTEGER, SSE, SSEUP, X87, X87UP, COMPLEX_X87, NO_CLASSという<br />引数のタイプがあるよ。<br /><br /><br /><blockquote><pre><br /><b>Classification</b> The size of each argument gets rounded up to eightbytes.<br />The basic types are assigned their natural classes:<br /><br />&#8226; Arguments of types (signed and unsigned) _Bool, char, short, int,<br />long, long long, and pointers are in the INTEGER class.<br />&#8226; Arguments of types float, double and __m64 are in class SSE.<br />（しばらく略）<br /></pre></blockquote><br /><br />超訳<br />(signed and unsigned) _Bool, char, short, int, long, long long, およびポインタは INTEGERだよ<br />float, double and __m64 はSSEだよ<br /><br />（この後、__float128とか構造体とかの説明がつづくが割愛）<br /><br /><br /><blockquote><pre><br /><b>Passing</b> Once arguments are classified, the registers get assigned (in left-to-right<br />order) for passing as follows:<br /><br />1. If the class is MEMORY, pass the argument on the stack.<br />2. If the class is INTEGER, the next available register of the sequence %rdi,<br />%rsi, %rdx, %rcx, %r8 and %r9 is used.<br />3. If the class is SSE, the next available SSE register is used, the registers are<br />taken in the order from %xmm0 to %xmm7.<br />4. （略）<br />5. （略）<br /></pre></blockquote><br /><br />超訳。<br />MEMORYならスタック渡し確定<br />INTEGERならrdi, rsi, rdx, rcx, r8, r9の順に使うよ<br />SSEならSSEレジスタをxmm0からxmm7の順につかうよ<br /><br /><blockquote><pre><br /> If there is no register available anymore for any eightbyte of an argument, the<br />whole argument is passed on the stack. If registers have already been assigned for<br />some eightbytes of this argument, those assignments get reverted.<br /><br /> Once registers are assigned, the arguments passed in memory are pushed on<br />the stack in reversed (right-to-left) order.<br /></pre></blockquote><br /><br />超訳<br />レジスタが足りなくなったらスタックを使って引数を渡すよ。<br />スタックには逆順（右から左）でpushするよ<br /><br /><br />で、ここで問題のセンテンスが現れる<br /><blockquote><pre><br /> For calls that may call functions that use varargs or stdargs (prototype-less<br />calls or calls to functions containing ellipsis (. . . ) in the declaration) %al is used<br />as hidden argument to specify the number of SSE registers used. The contents of<br />%al do not need to match exactly the number of registers, but must be an upper<br /></pre></blockquote><br /><br />超訳<br />varargsまたはstdargsな関数（プロトタイプがなかったり、宣言で...を使っていたり）を呼ぶときは<br />%al に何個SSEレジスタを使ったか隠し引数で入れるよ。<br /><br /><br />つまり、ここではprintf()的なまっとうな可変長引数の事を語っているだけであって、呼び出し元と呼び出し先で<br />関数の型が適合しない場合については何も語っていない。<br /><br />今回の場合で言うとsin関数はlibmの中では<br />	double sin(double)<br />という型でコンパイルされていて、呼び出し側では<br />	double f(long, ...)<br />という型だと思ってcallしている。<br /><br />じゃあ、実際に何が起こるかを示すためにテストプログラムを書いてみた。<br /><br />main.c<br /><blockquote><pre><br />#define _GNU_SOURCE<br />#include <dlfcn.h><br />#include <stdio.h><br /><br />void f1(void) {<br />        double (*func)(long, ...);<br />        double d = 57.0;<br />        long l = *(long*)&d;<br />        double ret;<br /><br />        func = dlsym(RTLD_DEFAULT, "func");<br />        ret = func(l);<br />        printf("%f\n",ret);<br />}<br /><br />int main(void)<br />{<br />        f1();<br />        return 0;<br />}<br /></pre></blockquote><br /><br />f.c<br /><blockquote><pre><br />double func(double d)<br />{<br />        return d*2;<br />}<br /></pre></blockquote><br /><br />実行結果<br /><blockquote><pre><br />% gcc *.c -ldl -Wall -g  -rdynamic; ./a.out<br />0.000000<br /></pre></blockquote><br /><br />はい、57*2で114 が返ってくるはずが0が返ってきてしまいました。<br /><br />んではdisassemble, <br /><br /><blockquote><pre><br />0000000000400834 <func>:<br />  400834:       55                      push   %rbp<br />  400835:       48 89 e5                mov    %rsp,%rbp<br />  400838:       f2 0f 11 45 f8          movsd  %xmm0,-0x8(%rbp)<br />  40083d:       f2 0f 10 45 f8          movsd  -0x8(%rbp),%xmm0<br />  400842:       f2 0f 58 c0             addsd  %xmm0,%xmm0<br />  400846:       c9                      leaveq<br />  400847:       c3                      retq<br /></pre></blockquote><br /><br />funcでは素直にxmm0を引数だと思って二倍しています。<br /><br /><blockquote><pre><br />00000000004008e0 <f1>:<br />  4008e0:       55                      push   %rbp<br />  4008e1:       48 89 e5                mov    %rsp,%rbp<br />  4008e4:       48 83 ec 20             sub    $0x20,%rsp<br />  4008e8:       48 b8 00 00 00 00 00    mov    $0x404c800000000000,%rax<br />  4008ef:       80 4c 40<br />  4008f2:       48 89 45 e0             mov    %rax,-0x20(%rbp)<br />  4008f6:       48 8d 45 e0             lea    -0x20(%rbp),%rax<br />  4008fa:       48 8b 00                mov    (%rax),%rax<br />  4008fd:       48 89 45 f0             mov    %rax,-0x10(%rbp)<br />  400901:       b8 48 0b 40 00          mov    $0x400b48,%eax<br />  400906:       48 89 c6                mov    %rax,%rsi<br />  400909:       bf 00 00 00 00          mov    $0x0,%edi<br />  40090e:       e8 2d fe ff ff          callq  400740 <dlsym@plt><br />  400913:       48 89 45 e8             mov    %rax,-0x18(%rbp)<br />  400917:       48 8b 45 f0             mov    -0x10(%rbp),%rax<br />  40091b:       48 8b 55 e8             mov    -0x18(%rbp),%rdx<br />  40091f:       48 89 c7                mov    %rax,%rdi<br />  400922:       b8 00 00 00 00          mov    $0x0,%eax<br />  400927:       ff d2                   callq  *%rdx<br />  400929:       f2 0f 11 45 f8          movsd  %xmm0,-0x8(%rbp)<br />  40092e:       b8 4d 0b 40 00          mov    $0x400b4d,%eax<br />  400933:       f2 0f 10 45 f8          movsd  -0x8(%rbp),%xmm0<br />  400938:       48 89 c7                mov    %rax,%rdi<br />  40093b:       b8 01 00 00 00          mov    $0x1,%eax<br />  400940:       e8 db fd ff ff          callq  400720 <printf@plt><br />  400945:       c9                      leaveq<br />  400946:       c3<br /></pre></blockquote><br /><br />でもf1ではrdi（INTEGERの第一引数）に l を、eaxに0を入れて関数コールしています。<br /><br />つまり、これが起きていることのすべてです。<br />呼び出し側がrdiに引数を詰んでいるのに、呼び出され側はxmm0を呼んでいるのですから<br />正しい答えが返るはずがありません。<br /><br />というわけで、これはdlモジュール制作者のABIの誤読ですね。<br />なお、Cの規格的には呼び出し元と呼び出し先で関数型が適合しない場合は未定義。たぶん、dlモジュール作者は規格を元に考えたのではなく<br /><br />１）全CPUアーキテクチャでlongで無理矢理callしても安心と考えた。または<br />２）x86_32 だけで動けばいいや。と割り切った<br /><br />のどちらかだと思いますが、イマドキx86_64は普通ですからねぇ。。。<br /><br />現在のインターフェースだと直しようがないので、RubyのCFuncの仕様を大きく変えないと x86_64対応は出来ないでしょう。<br />というわけで、RubyユーザのみなさんはCFuncでfloat, doubleを使わないようにしておくと将来幸せになれるかもしれないというお話でした。<br /><br />ではでは<br /><br /><br />追記： なぜこの問題がx86_64だけで発生するのかを、つらつらと考えてみたのだが、やはり歴史的な理由だろう。昔は関数宣言を忘れるとか当たり前だったので、昔からあるアーキだと、こういう関数型が不適合な呼び出しに対してABIを寛容に作ることが多かったのではないか？<br /><br />追記２： 関数の型の適合性とか安易に書いた気がする。でもCの規格を読み直す気がおきない。めどい<br />簡単にいうと<br /> １）呼び出し元と呼び出し先が両方とも関数宣言有り： 引数、戻り値の型が全部一致していた場合のみOK<br /> ２）どちらかが宣言なし： 戻り値の型は厳密一致が必要だけど、引数は型がshortとintみたいに十分近ければOK<br />みたいなノリだったと思う。今回はケース１だけど、２の基準で反転してもアウトという論外さ<br /><br /> ]]>
</content:encoded>
<dc:subject>プログラミング</dc:subject>
<dc:date>2010-01-19T23:47:20+09:00</dc:date>
<dc:creator>kosaki</dc:creator>
<dc:publisher>FC2-BLOG</dc:publisher>
</item>
<item rdf:about="http://mkosaki.blog46.fc2.com/blog-entry-1068.html">
<link>http://mkosaki.blog46.fc2.com/blog-entry-1068.html</link>
<title>kernel watch 12月号</title>
<description> 公開されたようです。執筆用の実験で、snap-shot mergeした領域をディストリ付属の古いLVMツールで触ってしまい（とゆーか、OS起動時に勝手に触るんだが）ストレージを壊してしまいさんざんでした。ほむり http://www.atmarkit.co.jp/flinux/rensai/watch2009/watch12a.html
 </description>
<content:encoded>
<![CDATA[ 公開されたようです。<br />執筆用の実験で、snap-shot mergeした領域をディストリ付属の古いLVMツールで触ってしまい<br />（とゆーか、OS起動時に勝手に触るんだが）<br />ストレージを壊してしまいさんざんでした。ほむり <br /><br /><a href="http://www.atmarkit.co.jp/flinux/rensai/watch2009/watch12a.html" target="_blank" title="http://www.atmarkit.co.jp/flinux/rensai/watch2009/watch12a.html">http://www.atmarkit.co.jp/flinux/rensai/watch2009/watch12a.html</a> ]]>
</content:encoded>
<dc:subject>linux</dc:subject>
<dc:date>2010-01-13T08:32:15+09:00</dc:date>
<dc:creator>kosaki</dc:creator>
<dc:publisher>FC2-BLOG</dc:publisher>
</item>
</rdf:RDF>